directus-template-cli 0.7.3 → 0.7.5

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.
@@ -1,19 +1,19 @@
1
- import { note, outro, spinner, log as clackLog } from '@clack/prompts';
1
+ import { log as clackLog, note, outro, spinner } from '@clack/prompts';
2
2
  import { ux } from '@oclif/core';
3
+ import dotenv from 'dotenv';
3
4
  import { execa } from 'execa';
4
5
  import { downloadTemplate } from 'giget';
5
6
  import { glob } from 'glob';
6
7
  import fs from 'node:fs';
7
8
  import { detectPackageManager, installDependencies } from 'nypm';
8
9
  import path from 'pathe';
9
- import dotenv from 'dotenv';
10
10
  import ApplyCommand from '../../commands/apply.js';
11
11
  import { createDocker } from '../../services/docker.js';
12
+ import { BSL_LICENSE_CTA, BSL_LICENSE_HEADLINE, BSL_LICENSE_TEXT, pinkText } from '../constants.js';
12
13
  import catchError from '../utils/catch-error.js';
13
14
  import { createGigetString, parseGitHubUrl } from '../utils/parse-github-url.js';
14
15
  import { readTemplateConfig } from '../utils/template-config.js';
15
16
  import { DOCKER_CONFIG } from './config.js';
16
- import { BSL_LICENSE_TEXT, BSL_LICENSE_HEADLINE, BSL_LICENSE_CTA, pinkText } from '../constants.js';
17
17
  export async function init({ dir, flags }) {
18
18
  // Check target directory
19
19
  const shouldForce = flags.overwriteDir;
@@ -36,15 +36,13 @@ export async function init({ dir, flags }) {
36
36
  });
37
37
  // For direct URLs, we need to check if there's a directus directory
38
38
  // If not, assume the entire repo is a directus template
39
- if (isDirectUrl) {
40
- if (!fs.existsSync(directusDir)) {
41
- // Move all files to directus directory
42
- fs.mkdirSync(directusDir, { recursive: true });
43
- const files = fs.readdirSync(dir);
44
- for (const file of files) {
45
- if (file !== 'directus') {
46
- fs.renameSync(path.join(dir, file), path.join(directusDir, file));
47
- }
39
+ if (isDirectUrl && !fs.existsSync(directusDir)) {
40
+ // Move all files to directus directory
41
+ fs.mkdirSync(directusDir, { recursive: true });
42
+ const files = fs.readdirSync(dir);
43
+ for (const file of files) {
44
+ if (file !== 'directus') {
45
+ fs.renameSync(path.join(dir, file), path.join(directusDir, file));
48
46
  }
49
47
  }
50
48
  }
@@ -161,7 +159,9 @@ export async function init({ dir, flags }) {
161
159
  const relativeDir = path.relative(process.cwd(), dir);
162
160
  const directusUrl = directusInfo.url ?? 'http://localhost:8055';
163
161
  const directusText = `- Directus is running on ${directusUrl}. \n`;
164
- const directusLoginText = `- You can login with the email: ${pinkText(directusInfo.email)} and password: ${pinkText(directusInfo.password)}. \n`;
162
+ const directusLoginText = directusInfo.email && directusInfo.password
163
+ ? `- You can login with the email: ${pinkText(directusInfo.email)} and password: ${pinkText(directusInfo.password)}. \n`
164
+ : `- Complete the onboarding form at ${pinkText(directusInfo.url || 'http://localhost:8055')} to create your admin account. \n`;
165
165
  const frontendText = flags.frontend ? `- To start the frontend, run ${pinkText(`cd ${flags.frontend}`)} and then ${pinkText(`${packageManager?.name} run dev`)}. \n` : '';
166
166
  const projectText = `- Navigate to your project directory using ${pinkText(`cd ${relativeDir}`)}. \n`;
167
167
  const readmeText = '- Review the \`./README.md\` file for more information and next steps.';
@@ -3,6 +3,7 @@ export interface ApplyFlags {
3
3
  dashboards: boolean;
4
4
  directusToken: string;
5
5
  directusUrl: string;
6
+ disableTelemetry?: boolean;
6
7
  extensions: boolean;
7
8
  files: boolean;
8
9
  flows: boolean;
@@ -16,7 +17,6 @@ export interface ApplyFlags {
16
17
  userEmail: string;
17
18
  userPassword: string;
18
19
  users?: boolean;
19
- disableTelemetry?: boolean;
20
20
  }
21
21
  export declare const loadFlags: readonly ["content", "dashboards", "extensions", "files", "flows", "permissions", "schema", "settings", "users"];
22
22
  export declare function validateProgrammaticFlags(flags: ApplyFlags): ApplyFlags;
@@ -36,11 +36,9 @@ const removeRequiredorIsNullable = (field) => {
36
36
  field.meta.required = false;
37
37
  }
38
38
  if (field.schema?.is_nullable === false) {
39
- // eslint-disable-next-line camelcase
40
39
  field.schema.is_nullable = true;
41
40
  }
42
41
  if (field.schema?.is_unique === true) {
43
- // eslint-disable-next-line camelcase
44
42
  field.schema.is_unique = false;
45
43
  }
46
44
  return field;
@@ -20,12 +20,10 @@ const customDefu = createDefu((obj, key, value) => {
20
20
  });
21
21
  function mergeArrays(key, current, incoming) {
22
22
  const mergeKeys = {
23
- /* eslint-disable camelcase */
24
23
  basemaps: ['key'],
25
24
  custom_aspect_ratios: ['key'],
26
25
  module_bar: ['id', 'type'],
27
26
  storage_asset_presets: ['key'],
28
- /* eslint-enable camelcase */
29
27
  };
30
28
  const keys = mergeKeys[key];
31
29
  if (!keys)
package/dist/lib/sdk.d.ts CHANGED
@@ -14,7 +14,7 @@ export declare class DirectusError extends Error {
14
14
  parseErrors(): Promise<void>;
15
15
  }
16
16
  declare class Api {
17
- client: (RestClient<Schema> & AuthenticationClient<Schema>) | undefined;
17
+ client: (AuthenticationClient<Schema> & RestClient<Schema>) | undefined;
18
18
  private authData;
19
19
  private limiter;
20
20
  constructor();
@@ -11,10 +11,10 @@ export interface ExtensionSchema {
11
11
  name: string;
12
12
  type: ExtensionType;
13
13
  }>;
14
- entrypoint: {
14
+ entrypoint: string | {
15
15
  api: string;
16
16
  app: string;
17
- } | string;
17
+ };
18
18
  host: string;
19
19
  local: boolean;
20
20
  name: string;
@@ -3,16 +3,16 @@ export interface DirectusTemplateFrontend {
3
3
  path: string;
4
4
  }
5
5
  export interface DirectusTemplateConfig {
6
- name: string;
7
6
  description: string;
8
- template: string | null;
9
7
  frontends: {
10
8
  [key: string]: DirectusTemplateFrontend;
11
9
  };
10
+ name: string;
11
+ template: null | string;
12
12
  }
13
13
  export interface TemplatePackageJson {
14
- name: string;
15
- version: string;
16
14
  description: string;
17
15
  'directus:template'?: DirectusTemplateConfig;
16
+ name: string;
17
+ version: string;
18
18
  }
@@ -50,8 +50,8 @@ export async function animatedBunny(customMessage) {
50
50
  }
51
51
  }, 25);
52
52
  try {
53
- // Run the animation for the duration of typing plus 1 second
54
- await new Promise(resolve => setTimeout(resolve, saying.length * 25 + 1000));
53
+ // Run the animation for the duration of typing plus 500ms
54
+ await new Promise(resolve => setTimeout(resolve, saying.length * 25 + 500));
55
55
  }
56
56
  finally {
57
57
  cleanup();
@@ -23,12 +23,12 @@ export declare function getDirectusEmailAndPassword(): Promise<{
23
23
  * Initialize the Directus API with the provided flags and log in the user
24
24
  * @param flags - The validated ApplyFlags
25
25
  * @returns {Promise<void>} - Returns nothing
26
- */
26
+ */
27
27
  export declare function initializeDirectusApi(flags: AuthFlags): Promise<void>;
28
28
  /**
29
- * Validate the authentication flags
30
- * @param flags - The AuthFlags
31
- * @returns {void} - Errors if the flags are invalid
32
- */
29
+ * Validate the authentication flags
30
+ * @param flags - The AuthFlags
31
+ * @returns {void} - Errors if the flags are invalid
32
+ */
33
33
  export declare function validateAuthFlags(flags: AuthFlags): void;
34
34
  export {};
@@ -1,18 +1,18 @@
1
+ import { isCancel, log, password, text } from '@clack/prompts';
1
2
  import { readMe } from '@directus/sdk';
2
- import { text, log, isCancel, password } from '@clack/prompts';
3
3
  import { ux } from '@oclif/core';
4
+ import { DEFAULT_DIRECTUS_URL } from '../../lib/constants.js';
4
5
  import { api } from '../sdk.js';
5
6
  import catchError from './catch-error.js';
6
7
  import validateUrl from './validate-url.js';
7
- import { DEFAULT_DIRECTUS_URL } from '../../lib/constants.js';
8
8
  /**
9
9
  * Get the Directus URL from the user
10
10
  * @returns The Directus URL
11
11
  */
12
12
  export async function getDirectusUrl() {
13
13
  const directusUrl = await text({
14
- placeholder: DEFAULT_DIRECTUS_URL,
15
14
  message: 'What is your Directus URL?',
15
+ placeholder: DEFAULT_DIRECTUS_URL,
16
16
  });
17
17
  if (isCancel(directusUrl)) {
18
18
  log.info('Exiting...');
@@ -37,8 +37,8 @@ export async function getDirectusUrl() {
37
37
  */
38
38
  export async function getDirectusToken(directusUrl) {
39
39
  const directusToken = await text({
40
- placeholder: 'admin-token-here',
41
40
  message: 'What is your Directus Admin Token?',
41
+ placeholder: 'admin-token-here',
42
42
  });
43
43
  if (isCancel(directusToken)) {
44
44
  log.info('Exiting...');
@@ -92,7 +92,7 @@ export async function getDirectusEmailAndPassword() {
92
92
  * Initialize the Directus API with the provided flags and log in the user
93
93
  * @param flags - The validated ApplyFlags
94
94
  * @returns {Promise<void>} - Returns nothing
95
- */
95
+ */
96
96
  export async function initializeDirectusApi(flags) {
97
97
  api.initialize(flags.directusUrl);
98
98
  try {
@@ -112,10 +112,10 @@ export async function initializeDirectusApi(flags) {
112
112
  }
113
113
  }
114
114
  /**
115
- * Validate the authentication flags
116
- * @param flags - The AuthFlags
117
- * @returns {void} - Errors if the flags are invalid
118
- */
115
+ * Validate the authentication flags
116
+ * @param flags - The AuthFlags
117
+ * @returns {void} - Errors if the flags are invalid
118
+ */
119
119
  export function validateAuthFlags(flags) {
120
120
  if (!flags.directusUrl) {
121
121
  ux.error('Directus URL is required.');
@@ -1,8 +1,8 @@
1
1
  import { ux } from '@oclif/core';
2
+ import { getExecutionContext } from '../../services/execution-context.js';
3
+ import { captureException } from '../../services/posthog.js';
2
4
  import { DirectusError } from '../sdk.js';
3
5
  import { logger } from '../utils/logger.js';
4
- import { captureException } from '../../services/posthog.js';
5
- import { getExecutionContext } from '../../services/execution-context.js';
6
6
  /**
7
7
  * Handles errors by formatting them and optionally logging to console and file.
8
8
  * @param error - The error to be handled.
@@ -11,7 +11,7 @@ import { getExecutionContext } from '../../services/execution-context.js';
11
11
  */
12
12
  export default function catchError(error, options = {}) {
13
13
  const { context = {}, fatal = false, logToFile = true } = options;
14
- const { distinctId, disableTelemetry } = getExecutionContext();
14
+ const { disableTelemetry, distinctId } = getExecutionContext();
15
15
  let errorMessage;
16
16
  if (error instanceof DirectusError) {
17
17
  errorMessage = error.message;
@@ -24,7 +24,7 @@ export default function catchError(error, options = {}) {
24
24
  }
25
25
  // Capture exception before logging/exiting
26
26
  if (!disableTelemetry && distinctId) {
27
- captureException({ error, distinctId, properties: { context } });
27
+ captureException({ distinctId, error, properties: { context } });
28
28
  }
29
29
  // Format the error message with context if provided
30
30
  const formattedMessage = [
@@ -30,7 +30,7 @@ class Logger {
30
30
  this.writeToFile(`Log started at ${timestamp}\n`);
31
31
  }
32
32
  sanitize(obj) {
33
- const sensitiveFields = new Set(['password', 'token', 'secret', 'key', 'authorization', 'email', 'access_token', 'refresh_token']);
33
+ const sensitiveFields = new Set(['access_token', 'authorization', 'email', 'key', 'password', 'refresh_token', 'secret', 'token']);
34
34
  return Object.fromEntries(Object.entries(obj).map(([key, value]) => {
35
35
  if (sensitiveFields.has(key.toLowerCase())) {
36
36
  return [key, '********'];
@@ -25,7 +25,7 @@ function cleanGitHubUrl(url) {
25
25
  parsed.hash = '';
26
26
  return parsed.toString();
27
27
  }
28
- catch (error) {
28
+ catch {
29
29
  // If URL parsing fails, just remove .git suffix
30
30
  return url.replace(/\.git$/, '');
31
31
  }
@@ -80,7 +80,7 @@ export function parseGitHubUrl(url) {
80
80
  // Ensure path is undefined if empty string
81
81
  if (path === '')
82
82
  path = undefined;
83
- return { owner, repo, path, ref };
83
+ return { owner, path, ref, repo };
84
84
  }
85
85
  catch (error) {
86
86
  throw new Error(`Invalid GitHub URL: ${url}. Error: ${error.message}`);
@@ -92,7 +92,7 @@ export function parseGitHubUrl(url) {
92
92
  const [owner, repo, ...rest] = parts;
93
93
  const path = rest.length > 0 ? rest.join('/') : undefined;
94
94
  // Assume default branch for simple paths unless we add ref detection here too
95
- return { owner, repo, path, ref: DEFAULT_BRANCH };
95
+ return { owner, path, ref: DEFAULT_BRANCH, repo };
96
96
  }
97
97
  // Handle simple template names using DEFAULT_REPO
98
98
  return {
@@ -1,6 +1,6 @@
1
1
  import fs from 'node:fs';
2
- import path from 'pathe';
3
2
  import { cwd } from 'node:process';
3
+ import path from 'pathe';
4
4
  /**
5
5
  * Resolves a given path to an absolute path and checks if it exists.
6
6
  * @param inputPath The path to resolve.
@@ -2,6 +2,6 @@ interface Template {
2
2
  directoryPath: string;
3
3
  templateName: string;
4
4
  }
5
- export declare function readTemplate(directoryPath: string): Promise<Template | null>;
5
+ export declare function readTemplate(directoryPath: string): Promise<null | Template>;
6
6
  export declare function readAllTemplates(directoryPath: string): Promise<Template[]>;
7
7
  export {};
@@ -1,4 +1,2 @@
1
- const SENSITIVE_FLAGS = ['userEmail', 'userPassword', 'directusToken'];
2
- export const sanitizeFlags = (flags) => {
3
- return Object.fromEntries(Object.entries(flags).filter(([key]) => !SENSITIVE_FLAGS.includes(key)));
4
- };
1
+ const SENSITIVE_FLAGS = new Set(['directusToken', 'userEmail', 'userPassword']);
2
+ export const sanitizeFlags = (flags) => Object.fromEntries(Object.entries(flags).filter(([key]) => !SENSITIVE_FLAGS.has(key)));
@@ -13,4 +13,4 @@ export interface TemplateInfo {
13
13
  * @returns Template configuration and frontend options
14
14
  * @throws Error if package.json is missing or invalid
15
15
  */
16
- export declare function readTemplateConfig(dir: string): TemplateInfo | null;
16
+ export declare function readTemplateConfig(dir: string): null | TemplateInfo;
@@ -28,7 +28,7 @@ export function readTemplateConfig(dir) {
28
28
  frontendOptions,
29
29
  };
30
30
  }
31
- catch (error) {
31
+ catch {
32
32
  return null;
33
33
  }
34
34
  }
@@ -1,7 +1,7 @@
1
- import { spinner, log } from '@clack/prompts';
1
+ import { log, spinner } from '@clack/prompts';
2
+ import { ux } from '@oclif/core';
2
3
  import { execa } from 'execa';
3
4
  import net from 'node:net';
4
- import { ux } from '@oclif/core';
5
5
  import catchError from '../lib/utils/catch-error.js';
6
6
  import { waitFor } from '../lib/utils/wait.js';
7
7
  /**
@@ -41,11 +41,11 @@ async function checkPort(port) {
41
41
  */
42
42
  async function checkRequiredPorts() {
43
43
  const portsToCheck = [
44
- { port: 8055, name: 'Directus API' },
45
- { port: 5432, name: 'PostgreSQL' },
44
+ { name: 'Directus API', port: 8055 },
45
+ { name: 'PostgreSQL', port: 5432 },
46
46
  ];
47
47
  let hasConflicts = false;
48
- for (const { port, name } of portsToCheck) {
48
+ for (const { name, port } of portsToCheck) {
49
49
  const status = await checkPort(port);
50
50
  if (status.inUse) {
51
51
  hasConflicts = true;
@@ -63,27 +63,32 @@ async function checkRequiredPorts() {
63
63
  * @returns {Promise<DockerCheckResult>} Docker installation and running status
64
64
  */
65
65
  async function checkDocker() {
66
+ // First check if Docker is installed
66
67
  try {
67
- // Check if Docker is installed
68
- const versionResult = await execa('docker', ['--version']);
69
- const isInstalled = versionResult.exitCode === 0;
70
- if (!isInstalled) {
71
- return { installed: false, message: 'Docker is not installed. Please install Docker at https://docs.docker.com/get-started/get-docker/', running: false };
72
- }
73
- // Check if Docker daemon is running
74
- const statusResult = await execa('docker', ['info']);
75
- const isRunning = statusResult.exitCode === 0;
68
+ await execa('docker', ['--version']);
69
+ }
70
+ catch {
71
+ // Docker is not installed
72
+ return {
73
+ installed: false,
74
+ message: 'Docker is not installed. Please install Docker at https://docs.docker.com/get-started/get-docker/',
75
+ running: false,
76
+ };
77
+ }
78
+ // Docker is installed, now check if it's running
79
+ try {
80
+ await execa('docker', ['info']);
76
81
  return {
77
82
  installed: true,
78
83
  message: 'Docker is installed and running.',
79
- running: isRunning,
84
+ running: true,
80
85
  };
81
86
  }
82
87
  catch {
83
- // If any command fails, Docker is either not installed or not running
88
+ // Docker is installed but not running
84
89
  return {
85
- installed: false,
86
- message: 'Docker is not running. Please start Docker and try again.',
90
+ installed: true,
91
+ message: 'Docker is installed but not running. Please start Docker before running the init command.',
87
92
  running: false,
88
93
  };
89
94
  }
@@ -129,7 +134,7 @@ async function checkImagesExist(imageNames) {
129
134
  // This catch block might be redundant due to allSettled, but good for safety
130
135
  log.error('Error checking for Docker images.');
131
136
  catchError(error, {
132
- context: { imageNames, function: 'checkImagesExist' },
137
+ context: { function: 'checkImagesExist', imageNames },
133
138
  fatal: false,
134
139
  logToFile: true,
135
140
  });
@@ -2,8 +2,8 @@
2
2
  * Defines the structure for the execution context, holding telemetry information.
3
3
  */
4
4
  export interface ExecutionContext {
5
- distinctId?: string;
6
5
  disableTelemetry?: boolean;
6
+ distinctId?: string;
7
7
  }
8
8
  /**
9
9
  * Sets the global execution context.
@@ -6,9 +6,9 @@ interface GitHubUrlParts {
6
6
  repo: string;
7
7
  }
8
8
  export interface TemplateInfo {
9
+ description?: string;
9
10
  id: string;
10
11
  name: string;
11
- description?: string;
12
12
  }
13
13
  export interface GitHubService {
14
14
  getTemplateDirectories(template: string, customUrl?: string): Promise<string[]>;
@@ -1,7 +1,7 @@
1
+ import { ux } from '@oclif/core';
1
2
  import { Octokit } from '@octokit/rest';
2
3
  import { DEFAULT_REPO } from '../lib/constants.js';
3
4
  import { parseGitHubUrl } from '../lib/utils/parse-github-url.js';
4
- import { ux } from '@oclif/core';
5
5
  export function createGitHub(token) {
6
6
  const octokit = new Octokit({
7
7
  auth: token,
@@ -19,9 +19,9 @@ export function createGitHub(token) {
19
19
  try {
20
20
  const { data } = await octokit.rest.repos.getContent({
21
21
  owner: repo.owner,
22
- repo: repo.repo,
23
22
  path: repo.path || '',
24
23
  ref: repo.ref,
24
+ repo: repo.repo,
25
25
  });
26
26
  if (!Array.isArray(data))
27
27
  return [];
@@ -31,7 +31,7 @@ export function createGitHub(token) {
31
31
  .filter(item => item.type === 'dir')
32
32
  .map(item => item.name);
33
33
  }
34
- catch (error) {
34
+ catch {
35
35
  // If we can't get contents, return empty array
36
36
  // This indicates no frontends are available
37
37
  return [];
@@ -53,7 +53,7 @@ export function createGitHub(token) {
53
53
  .filter(item => item.type === 'dir' && item.name !== 'directus')
54
54
  .map(item => item.name);
55
55
  }
56
- catch (error) {
56
+ catch {
57
57
  // If we can't get contents, return empty array
58
58
  return [];
59
59
  }
@@ -74,13 +74,13 @@ export function createGitHub(token) {
74
74
  const packageJsonPath = joinPath(parsed.path || '', 'package.json');
75
75
  try {
76
76
  const { data: packageJsonContent } = await octokit.rest.repos.getContent({
77
- owner: parsed.owner,
78
- repo: parsed.repo,
79
- path: packageJsonPath,
80
- ref: parsed.ref,
81
77
  mediaType: {
82
78
  format: 'raw',
83
79
  },
80
+ owner: parsed.owner,
81
+ path: packageJsonPath,
82
+ ref: parsed.ref,
83
+ repo: parsed.repo,
84
84
  });
85
85
  // getContent with mediaType: raw returns string directly
86
86
  if (typeof packageJsonContent === 'string') {
@@ -103,7 +103,7 @@ export function createGitHub(token) {
103
103
  }
104
104
  }
105
105
  // Return a single item array for the direct URL case
106
- return [{ id: customUrl, name, description }];
106
+ return [{ description, id: customUrl, name }];
107
107
  }
108
108
  const repo = customUrl ? parseGitHubUrl(customUrl) : DEFAULT_REPO;
109
109
  const { data: rootContent } = await octokit.rest.repos.getContent({
@@ -116,19 +116,19 @@ export function createGitHub(token) {
116
116
  return [];
117
117
  const directories = rootContent.filter(item => item.type === 'dir');
118
118
  // Fetch package.json for each directory concurrently
119
- let templateInfos = await Promise.all(directories.map(async (dir) => {
119
+ const templateInfos = await Promise.all(directories.map(async (dir) => {
120
120
  const packageJsonPath = joinPath(repo.path || '', dir.path, 'package.json');
121
- let name = dir.name;
121
+ let { name } = dir;
122
122
  let description;
123
123
  try {
124
124
  const { data: packageJsonContent } = await octokit.rest.repos.getContent({
125
- owner: repo.owner,
126
- repo: repo.repo,
127
- path: packageJsonPath,
128
- ref: repo.ref,
129
125
  mediaType: {
130
126
  format: 'raw',
131
127
  },
128
+ owner: repo.owner,
129
+ path: packageJsonPath,
130
+ ref: repo.ref,
131
+ repo: repo.repo,
132
132
  });
133
133
  // getContent with mediaType: raw returns string directly
134
134
  if (typeof packageJsonContent === 'string') {
@@ -149,9 +149,9 @@ export function createGitHub(token) {
149
149
  }
150
150
  }
151
151
  return {
152
+ description,
152
153
  id: dir.name,
153
154
  name,
154
- description,
155
155
  };
156
156
  }));
157
157
  // Sort the templates to put "blank" last
@@ -24,16 +24,16 @@ export declare function shutdown(debug?: boolean): Promise<void>;
24
24
  * @param options.properties Optional additional properties to track
25
25
  * @param options.debug Whether to log debug information
26
26
  */
27
- export declare function track({ lifecycle, distinctId, command, flags, runId, message, config, properties, debug }: {
28
- lifecycle: 'start' | 'complete' | 'error';
29
- message?: string;
30
- distinctId: string;
27
+ export declare function track({ command, config, debug, distinctId, flags, lifecycle, message, properties, runId }: {
31
28
  command?: string;
32
- flags?: Record<string, unknown>;
33
- runId?: string;
34
29
  config?: Config;
35
- properties?: Record<string, unknown>;
36
30
  debug?: boolean;
31
+ distinctId: string;
32
+ flags?: Record<string, unknown>;
33
+ lifecycle: 'complete' | 'error' | 'start';
34
+ message?: string;
35
+ properties?: Record<string, unknown>;
36
+ runId?: string;
37
37
  }): void;
38
38
  /**
39
39
  * Manually capture an exception in PostHog
@@ -42,9 +42,9 @@ export declare function track({ lifecycle, distinctId, command, flags, runId, me
42
42
  * @param properties Optional additional properties to track
43
43
  * @param debug Whether to log debug information
44
44
  */
45
- export declare function captureException({ error, distinctId, properties, debug }: {
46
- error: unknown;
45
+ export declare function captureException({ debug, distinctId, error, properties }: {
46
+ debug?: boolean;
47
47
  distinctId: string;
48
+ error: unknown;
48
49
  properties?: Record<string, unknown>;
49
- debug?: boolean;
50
50
  }): void;
@@ -1,6 +1,6 @@
1
1
  import { ux } from '@oclif/core';
2
2
  import { PostHog } from 'posthog-node';
3
- import { POSTHOG_PUBLIC_KEY, POSTHOG_HOST } from '../lib/constants.js';
3
+ import { POSTHOG_HOST, POSTHOG_PUBLIC_KEY } from '../lib/constants.js';
4
4
  import { sanitizeFlags } from '../lib/utils/sanitize-flags.js';
5
5
  // Create a singleton client using module scope
6
6
  let client = null;
@@ -14,8 +14,8 @@ export function getClient(debug = false) {
14
14
  ux.stdout('Initializing PostHog client...');
15
15
  if (!client) {
16
16
  client = new PostHog(POSTHOG_PUBLIC_KEY, {
17
- host: POSTHOG_HOST,
18
17
  disableGeoip: false,
18
+ host: POSTHOG_HOST,
19
19
  });
20
20
  // Add error handling
21
21
  client.on('error', err => {
@@ -58,14 +58,14 @@ export async function shutdown(debug = false) {
58
58
  * @param options.properties Optional additional properties to track
59
59
  * @param options.debug Whether to log debug information
60
60
  */
61
- export function track({ lifecycle, distinctId, command, flags, runId, message, config, properties = {}, debug = false }) {
61
+ export function track({ command, config, debug = false, distinctId, flags, lifecycle, message, properties = {}, runId }) {
62
62
  if (debug)
63
63
  ux.stdout('Tracking event...');
64
64
  const phClient = getClient(debug);
65
65
  const eventProperties = command
66
66
  ? {
67
- runId,
68
67
  message,
68
+ runId,
69
69
  ...properties,
70
70
  ...getEnvironmentInfo(config),
71
71
  // Always sanitize sensitive flags
@@ -91,7 +91,7 @@ export function track({ lifecycle, distinctId, command, flags, runId, message, c
91
91
  * @param properties Optional additional properties to track
92
92
  * @param debug Whether to log debug information
93
93
  */
94
- export function captureException({ error, distinctId, properties = {}, debug = false }) {
94
+ export function captureException({ debug = false, distinctId, error, properties = {} }) {
95
95
  if (debug)
96
96
  ux.stdout('Capturing exception...');
97
97
  const phClient = getClient(debug);