@mondaydotcomorg/z2h-cli 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +1 -4
- package/dist/esm/commands/create.d.ts.map +1 -1
- package/dist/esm/commands/create.mjs +1 -4
- package/dist/esm/index.mjs +18 -6
- package/dist/esm/migrations/auto-migrate.mjs +4 -4
- package/dist/esm/util/logger.d.ts.map +1 -1
- package/dist/esm/util/logger.mjs +2 -0
- package/dist/esm/util/tracker.d.ts +3 -0
- package/dist/esm/util/tracker.d.ts.map +1 -0
- package/dist/esm/util/tracker.mjs +20 -0
- package/dist/index.js +18 -6
- package/dist/migrations/auto-migrate.js +3 -3
- package/dist/util/logger.d.ts.map +1 -1
- package/dist/util/logger.js +2 -0
- package/dist/util/tracker.d.ts +3 -0
- package/dist/util/tracker.d.ts.map +1 -0
- package/dist/util/tracker.js +27 -0
- package/package.json +1 -1
- package/src/commands/create.ts +1 -4
- package/src/index.ts +18 -6
- package/src/migrations/auto-migrate.ts +4 -4
- package/src/util/logger.ts +2 -0
- package/src/util/tracker.ts +25 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA6BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA6BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFvF"}
|
package/dist/commands/create.js
CHANGED
|
@@ -96,10 +96,7 @@ async function createCommand(appName, opts) {
|
|
|
96
96
|
await fsExtra.copy(opts.htmlFile, path__default.default.join(appDir, 'src', 'page.html'));
|
|
97
97
|
}
|
|
98
98
|
util_logger.info(`installing dependencies for ${appName}...`);
|
|
99
|
-
await execa.execa('yarn', ['install'], {
|
|
100
|
-
cwd: workspace,
|
|
101
|
-
stdio: 'inherit',
|
|
102
|
-
});
|
|
99
|
+
await execa.execa('yarn', ['install'], { cwd: workspace, stdio: 'inherit' });
|
|
103
100
|
util_logger.output(`[z2h-cli] app ready at ${appDir}`, {
|
|
104
101
|
ok: true,
|
|
105
102
|
appDir,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA6BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"create.d.ts","sourceRoot":"","sources":["../../../src/commands/create.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AA6BD,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkFvF"}
|
|
@@ -90,10 +90,7 @@ async function createCommand(appName, opts) {
|
|
|
90
90
|
await copy(opts.htmlFile, path.join(appDir, 'src', 'page.html'));
|
|
91
91
|
}
|
|
92
92
|
info(`installing dependencies for ${appName}...`);
|
|
93
|
-
await execa('yarn', ['install'], {
|
|
94
|
-
cwd: workspace,
|
|
95
|
-
stdio: 'inherit',
|
|
96
|
-
});
|
|
93
|
+
await execa('yarn', ['install'], { cwd: workspace, stdio: 'inherit' });
|
|
97
94
|
output(`[z2h-cli] app ready at ${appDir}`, {
|
|
98
95
|
ok: true,
|
|
99
96
|
appDir,
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
3
4
|
import { devCommand } from './commands/dev.mjs';
|
|
4
5
|
import { buildCommand } from './commands/build.mjs';
|
|
5
6
|
import { cleanCommand } from './commands/clean.mjs';
|
|
@@ -9,8 +10,17 @@ import { createCommand } from './commands/create.mjs';
|
|
|
9
10
|
import { generateZ2HTokenCommand } from './commands/generate-z2h-token.mjs';
|
|
10
11
|
import { migrateCommand } from './commands/migrate.mjs';
|
|
11
12
|
import { errorLog, fail } from './util/logger.mjs';
|
|
13
|
+
import { trackDuration } from './util/tracker.mjs';
|
|
12
14
|
|
|
13
15
|
const { version } = createRequire(import.meta.url)('../package.json');
|
|
16
|
+
function getCwdAppName() {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(readFileSync('package.json', 'utf8')).name;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
14
24
|
async function main() {
|
|
15
25
|
const program = new Command();
|
|
16
26
|
program
|
|
@@ -34,12 +44,9 @@ async function main() {
|
|
|
34
44
|
.option('--json', 'emit structured JSON on stdout')
|
|
35
45
|
.action(async (opts) => {
|
|
36
46
|
try {
|
|
37
|
-
await buildCommand(opts);
|
|
47
|
+
await trackDuration('z2h_app_build_success', () => buildCommand(opts), { app_name: getCwdAppName() });
|
|
38
48
|
}
|
|
39
49
|
catch (err) {
|
|
40
|
-
// fail() emits a structured JSON error on stdout in --json mode and
|
|
41
|
-
// a red line on stderr in human mode, then exits. errorLog alone is
|
|
42
|
-
// silent in JSON mode, which leaves machine consumers with no signal.
|
|
43
50
|
fail(`build failed: ${err.message}`, { command: 'build' }, 2);
|
|
44
51
|
}
|
|
45
52
|
});
|
|
@@ -74,7 +81,9 @@ async function main() {
|
|
|
74
81
|
.option('--json', 'emit structured JSON on stdout')
|
|
75
82
|
.action(async (opts) => {
|
|
76
83
|
try {
|
|
77
|
-
await deployCommand(opts)
|
|
84
|
+
await trackDuration('z2h_app_deploy_success', () => deployCommand(opts), {
|
|
85
|
+
app_name: getCwdAppName(),
|
|
86
|
+
});
|
|
78
87
|
}
|
|
79
88
|
catch (err) {
|
|
80
89
|
fail(`deploy failed: ${err.message}`, { command: 'deploy' }, 2);
|
|
@@ -114,7 +123,10 @@ async function main() {
|
|
|
114
123
|
.option('--json', 'emit structured JSON on stdout')
|
|
115
124
|
.action(async (appName, opts) => {
|
|
116
125
|
try {
|
|
117
|
-
await createCommand(appName, opts)
|
|
126
|
+
await trackDuration('z2h_app_created', () => createCommand(appName, opts), {
|
|
127
|
+
app_name: appName,
|
|
128
|
+
template: opts.template ?? 'default',
|
|
129
|
+
});
|
|
118
130
|
}
|
|
119
131
|
catch (err) {
|
|
120
132
|
fail(`create failed: ${err.message}`, { command: 'create' }, 1);
|
|
@@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import { pathExists, readJson, writeJson, writeFile } from 'fs-extra';
|
|
5
5
|
import { execa } from 'execa';
|
|
6
6
|
import semver from 'semver';
|
|
7
|
-
import { warn, info } from '../util/logger.mjs';
|
|
7
|
+
import { warn, info, errorLog } from '../util/logger.mjs';
|
|
8
8
|
import { getWorkspaceHome, isZ2hWorkspace } from '../util/workspace.mjs';
|
|
9
9
|
|
|
10
10
|
const STATE_FILE = '.z2h-migrations-state.json';
|
|
@@ -151,9 +151,9 @@ async function autoMigrate(cliVersion, dryRun = false) {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
catch (err) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
const errorMessage = `migration "${name}" failed: ${err.message}`;
|
|
155
|
+
errorLog(`${errorMessage}\nSkipping remaining migrations — run "z2h-cli migrate" to retry.`);
|
|
156
|
+
throw new Error(errorMessage);
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
159
|
if (needsInstall) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/util/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../../src/util/logger.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAI1C,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAEpD;AAED,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAItC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAItC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAI1C;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAMzD;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,SAAI,GAAG,KAAK,CAW3F"}
|
package/dist/esm/util/logger.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
|
+
import { trackEvent } from './tracker.mjs';
|
|
2
3
|
|
|
3
4
|
let mode = 'human';
|
|
4
5
|
function setOutputMode(next) {
|
|
@@ -53,6 +54,7 @@ function fail(message, payload, exitCode = 1) {
|
|
|
53
54
|
process.stderr.write(pc.dim(` → ${payload.suggestedCommand}\n`));
|
|
54
55
|
}
|
|
55
56
|
}
|
|
57
|
+
trackEvent('z2h_cli_error', { action: payload.command ?? 'unknown', error: message });
|
|
56
58
|
process.exit(exitCode);
|
|
57
59
|
}
|
|
58
60
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../../src/util/tracker.ts"],"names":[],"mappings":"AAMA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAO5E;AAED,wBAAsB,aAAa,CAAC,CAAC,EACnC,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CAKZ"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
|
|
3
|
+
const DOORMAN_URL = 'https://track.bigbrain.me/prod/event';
|
|
4
|
+
const username = os.userInfo().username;
|
|
5
|
+
function trackEvent(name, data) {
|
|
6
|
+
void fetch(DOORMAN_URL, {
|
|
7
|
+
method: 'POST',
|
|
8
|
+
headers: { 'Content-Type': 'application/json' },
|
|
9
|
+
body: JSON.stringify({ name, source: 'z2h-cli', data: { username, ...data } }),
|
|
10
|
+
signal: AbortSignal.timeout(5000),
|
|
11
|
+
}).catch(() => { });
|
|
12
|
+
}
|
|
13
|
+
async function trackDuration(eventName, fn, data) {
|
|
14
|
+
const start = Date.now();
|
|
15
|
+
const result = await fn();
|
|
16
|
+
trackEvent(eventName, { ...data, duration_ms: Date.now() - start });
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { trackDuration, trackEvent };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const node_module = require('node:module');
|
|
2
2
|
const commander = require('commander');
|
|
3
|
+
const fs = require('node:fs');
|
|
3
4
|
const commands_dev = require('./commands/dev.js');
|
|
4
5
|
const commands_build = require('./commands/build.js');
|
|
5
6
|
const commands_clean = require('./commands/clean.js');
|
|
@@ -9,9 +10,18 @@ const commands_create = require('./commands/create.js');
|
|
|
9
10
|
const commands_generateZ2hToken = require('./commands/generate-z2h-token.js');
|
|
10
11
|
const commands_migrate = require('./commands/migrate.js');
|
|
11
12
|
const util_logger = require('./util/logger.js');
|
|
13
|
+
const util_tracker = require('./util/tracker.js');
|
|
12
14
|
|
|
13
15
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
14
16
|
const { version } = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.js', document.baseURI).href)))('../package.json');
|
|
17
|
+
function getCwdAppName() {
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(fs.readFileSync('package.json', 'utf8')).name;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
15
25
|
async function main() {
|
|
16
26
|
const program = new commander.Command();
|
|
17
27
|
program
|
|
@@ -35,12 +45,9 @@ async function main() {
|
|
|
35
45
|
.option('--json', 'emit structured JSON on stdout')
|
|
36
46
|
.action(async (opts) => {
|
|
37
47
|
try {
|
|
38
|
-
await commands_build.buildCommand(opts);
|
|
48
|
+
await util_tracker.trackDuration('z2h_app_build_success', () => commands_build.buildCommand(opts), { app_name: getCwdAppName() });
|
|
39
49
|
}
|
|
40
50
|
catch (err) {
|
|
41
|
-
// fail() emits a structured JSON error on stdout in --json mode and
|
|
42
|
-
// a red line on stderr in human mode, then exits. errorLog alone is
|
|
43
|
-
// silent in JSON mode, which leaves machine consumers with no signal.
|
|
44
51
|
util_logger.fail(`build failed: ${err.message}`, { command: 'build' }, 2);
|
|
45
52
|
}
|
|
46
53
|
});
|
|
@@ -75,7 +82,9 @@ async function main() {
|
|
|
75
82
|
.option('--json', 'emit structured JSON on stdout')
|
|
76
83
|
.action(async (opts) => {
|
|
77
84
|
try {
|
|
78
|
-
await commands_deploy.deployCommand(opts)
|
|
85
|
+
await util_tracker.trackDuration('z2h_app_deploy_success', () => commands_deploy.deployCommand(opts), {
|
|
86
|
+
app_name: getCwdAppName(),
|
|
87
|
+
});
|
|
79
88
|
}
|
|
80
89
|
catch (err) {
|
|
81
90
|
util_logger.fail(`deploy failed: ${err.message}`, { command: 'deploy' }, 2);
|
|
@@ -115,7 +124,10 @@ async function main() {
|
|
|
115
124
|
.option('--json', 'emit structured JSON on stdout')
|
|
116
125
|
.action(async (appName, opts) => {
|
|
117
126
|
try {
|
|
118
|
-
await commands_create.createCommand(appName, opts)
|
|
127
|
+
await util_tracker.trackDuration('z2h_app_created', () => commands_create.createCommand(appName, opts), {
|
|
128
|
+
app_name: appName,
|
|
129
|
+
template: opts.template ?? 'default',
|
|
130
|
+
});
|
|
119
131
|
}
|
|
120
132
|
catch (err) {
|
|
121
133
|
util_logger.fail(`create failed: ${err.message}`, { command: 'create' }, 1);
|
|
@@ -159,9 +159,9 @@ async function autoMigrate(cliVersion, dryRun = false) {
|
|
|
159
159
|
}
|
|
160
160
|
}
|
|
161
161
|
catch (err) {
|
|
162
|
-
|
|
163
|
-
util_logger.
|
|
164
|
-
|
|
162
|
+
const errorMessage = `migration "${name}" failed: ${err.message}`;
|
|
163
|
+
util_logger.errorLog(`${errorMessage}\nSkipping remaining migrations — run "z2h-cli migrate" to retry.`);
|
|
164
|
+
throw new Error(errorMessage);
|
|
165
165
|
}
|
|
166
166
|
}
|
|
167
167
|
if (needsInstall) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/util/logger.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,CAAC;AAI1C,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAEpD;AAED,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAItC;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAItC;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAI1C;AAED;;;GAGG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAMzD;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,SAAI,GAAG,KAAK,CAW3F"}
|
package/dist/util/logger.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
|
|
3
3
|
const pc = require('picocolors');
|
|
4
|
+
const util_tracker = require('./tracker.js');
|
|
4
5
|
|
|
5
6
|
const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
6
7
|
|
|
@@ -59,6 +60,7 @@ function fail(message, payload, exitCode = 1) {
|
|
|
59
60
|
process.stderr.write(pc__default.default.dim(` → ${payload.suggestedCommand}\n`));
|
|
60
61
|
}
|
|
61
62
|
}
|
|
63
|
+
util_tracker.trackEvent('z2h_cli_error', { action: payload.command ?? 'unknown', error: message });
|
|
62
64
|
process.exit(exitCode);
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tracker.d.ts","sourceRoot":"","sources":["../../src/util/tracker.ts"],"names":[],"mappings":"AAMA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAO5E;AAED,wBAAsB,aAAa,CAAC,CAAC,EACnC,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACpB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,CAAC,CAAC,CAKZ"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
const os = require('node:os');
|
|
4
|
+
|
|
5
|
+
const _interopDefault = e => e && e.__esModule ? e : { default: e };
|
|
6
|
+
|
|
7
|
+
const os__default = /*#__PURE__*/_interopDefault(os);
|
|
8
|
+
|
|
9
|
+
const DOORMAN_URL = 'https://track.bigbrain.me/prod/event';
|
|
10
|
+
const username = os__default.default.userInfo().username;
|
|
11
|
+
function trackEvent(name, data) {
|
|
12
|
+
void fetch(DOORMAN_URL, {
|
|
13
|
+
method: 'POST',
|
|
14
|
+
headers: { 'Content-Type': 'application/json' },
|
|
15
|
+
body: JSON.stringify({ name, source: 'z2h-cli', data: { username, ...data } }),
|
|
16
|
+
signal: AbortSignal.timeout(5000),
|
|
17
|
+
}).catch(() => { });
|
|
18
|
+
}
|
|
19
|
+
async function trackDuration(eventName, fn, data) {
|
|
20
|
+
const start = Date.now();
|
|
21
|
+
const result = await fn();
|
|
22
|
+
trackEvent(eventName, { ...data, duration_ms: Date.now() - start });
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
exports.trackDuration = trackDuration;
|
|
27
|
+
exports.trackEvent = trackEvent;
|
package/package.json
CHANGED
package/src/commands/create.ts
CHANGED
|
@@ -116,10 +116,7 @@ export async function createCommand(appName: string, opts: CreateOptions): Promi
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
info(`installing dependencies for ${appName}...`);
|
|
119
|
-
await execa('yarn', ['install'], {
|
|
120
|
-
cwd: workspace,
|
|
121
|
-
stdio: 'inherit',
|
|
122
|
-
});
|
|
119
|
+
await execa('yarn', ['install'], { cwd: workspace, stdio: 'inherit' });
|
|
123
120
|
|
|
124
121
|
output(`[z2h-cli] app ready at ${appDir}`, {
|
|
125
122
|
ok: true,
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
import { Command } from 'commander';
|
|
3
|
+
import { readFileSync } from 'node:fs';
|
|
3
4
|
import { devCommand } from './commands/dev';
|
|
4
5
|
import { buildCommand } from './commands/build';
|
|
5
6
|
import { cleanCommand } from './commands/clean';
|
|
@@ -9,9 +10,18 @@ import { createCommand } from './commands/create';
|
|
|
9
10
|
import { generateZ2HTokenCommand } from './commands/generate-z2h-token';
|
|
10
11
|
import { migrateCommand } from './commands/migrate';
|
|
11
12
|
import { errorLog, fail } from './util/logger';
|
|
13
|
+
import { trackDuration } from './util/tracker';
|
|
12
14
|
|
|
13
15
|
const { version } = createRequire(import.meta.url)('../package.json') as { version: string };
|
|
14
16
|
|
|
17
|
+
function getCwdAppName(): string | undefined {
|
|
18
|
+
try {
|
|
19
|
+
return (JSON.parse(readFileSync('package.json', 'utf8')) as { name?: string }).name;
|
|
20
|
+
} catch {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
15
25
|
async function main(): Promise<void> {
|
|
16
26
|
const program = new Command();
|
|
17
27
|
program
|
|
@@ -38,11 +48,8 @@ async function main(): Promise<void> {
|
|
|
38
48
|
.option('--json', 'emit structured JSON on stdout')
|
|
39
49
|
.action(async (opts: { json?: boolean }) => {
|
|
40
50
|
try {
|
|
41
|
-
await buildCommand(opts);
|
|
51
|
+
await trackDuration('z2h_app_build_success', () => buildCommand(opts), { app_name: getCwdAppName() });
|
|
42
52
|
} catch (err) {
|
|
43
|
-
// fail() emits a structured JSON error on stdout in --json mode and
|
|
44
|
-
// a red line on stderr in human mode, then exits. errorLog alone is
|
|
45
|
-
// silent in JSON mode, which leaves machine consumers with no signal.
|
|
46
53
|
fail(`build failed: ${(err as Error).message}`, { command: 'build' }, 2);
|
|
47
54
|
}
|
|
48
55
|
});
|
|
@@ -78,7 +85,9 @@ async function main(): Promise<void> {
|
|
|
78
85
|
.option('--json', 'emit structured JSON on stdout')
|
|
79
86
|
.action(async (opts: { dryRun?: boolean; json?: boolean }) => {
|
|
80
87
|
try {
|
|
81
|
-
await deployCommand(opts)
|
|
88
|
+
await trackDuration('z2h_app_deploy_success', () => deployCommand(opts), {
|
|
89
|
+
app_name: getCwdAppName(),
|
|
90
|
+
});
|
|
82
91
|
} catch (err) {
|
|
83
92
|
fail(`deploy failed: ${(err as Error).message}`, { command: 'deploy' }, 2);
|
|
84
93
|
}
|
|
@@ -120,7 +129,10 @@ async function main(): Promise<void> {
|
|
|
120
129
|
.option('--json', 'emit structured JSON on stdout')
|
|
121
130
|
.action(async (appName: string, opts: { template?: string; htmlFile?: string; json?: boolean }) => {
|
|
122
131
|
try {
|
|
123
|
-
await createCommand(appName, opts)
|
|
132
|
+
await trackDuration('z2h_app_created', () => createCommand(appName, opts), {
|
|
133
|
+
app_name: appName,
|
|
134
|
+
template: opts.template ?? 'default',
|
|
135
|
+
});
|
|
124
136
|
} catch (err) {
|
|
125
137
|
fail(`create failed: ${(err as Error).message}`, { command: 'create' }, 1);
|
|
126
138
|
}
|
|
@@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import { pathExists, readJson, writeJson, writeFile } from 'fs-extra';
|
|
5
5
|
import { execa } from 'execa';
|
|
6
6
|
import semver from 'semver';
|
|
7
|
-
import { info, warn } from '../util/logger';
|
|
7
|
+
import { info, warn, errorLog } from '../util/logger';
|
|
8
8
|
import { getWorkspaceHome, isZ2hWorkspace } from '../util/workspace';
|
|
9
9
|
|
|
10
10
|
const STATE_FILE = '.z2h-migrations-state.json';
|
|
@@ -199,9 +199,9 @@ export async function autoMigrate(cliVersion: string, dryRun = false): Promise<v
|
|
|
199
199
|
info(` ○ ${entry.description} (no changes needed)`);
|
|
200
200
|
}
|
|
201
201
|
} catch (err) {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
202
|
+
const errorMessage = `migration "${name}" failed: ${(err as Error).message}`;
|
|
203
|
+
errorLog(`${errorMessage}\nSkipping remaining migrations — run "z2h-cli migrate" to retry.`);
|
|
204
|
+
throw new Error(errorMessage);
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
|
package/src/util/logger.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import pc from 'picocolors';
|
|
2
|
+
import { trackEvent } from './tracker';
|
|
2
3
|
|
|
3
4
|
export type OutputMode = 'human' | 'json';
|
|
4
5
|
|
|
@@ -60,5 +61,6 @@ export function fail(message: string, payload: Record<string, unknown>, exitCode
|
|
|
60
61
|
process.stderr.write(pc.dim(` → ${payload.suggestedCommand}\n`));
|
|
61
62
|
}
|
|
62
63
|
}
|
|
64
|
+
trackEvent('z2h_cli_error', { action: (payload.command as string) ?? 'unknown', error: message });
|
|
63
65
|
process.exit(exitCode);
|
|
64
66
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
|
|
3
|
+
const DOORMAN_URL = 'https://track.bigbrain.me/prod/event';
|
|
4
|
+
|
|
5
|
+
const username = os.userInfo().username;
|
|
6
|
+
|
|
7
|
+
export function trackEvent(name: string, data: Record<string, unknown>): void {
|
|
8
|
+
void fetch(DOORMAN_URL, {
|
|
9
|
+
method: 'POST',
|
|
10
|
+
headers: { 'Content-Type': 'application/json' },
|
|
11
|
+
body: JSON.stringify({ name, source: 'z2h-cli', data: { username, ...data } }),
|
|
12
|
+
signal: AbortSignal.timeout(5000),
|
|
13
|
+
}).catch(() => {});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function trackDuration<T>(
|
|
17
|
+
eventName: string,
|
|
18
|
+
fn: () => Promise<T>,
|
|
19
|
+
data?: Record<string, unknown>
|
|
20
|
+
): Promise<T> {
|
|
21
|
+
const start = Date.now();
|
|
22
|
+
const result = await fn();
|
|
23
|
+
trackEvent(eventName, { ...data, duration_ms: Date.now() - start });
|
|
24
|
+
return result;
|
|
25
|
+
}
|