@contentful/experience-design-system-cli 2.23.2-dev-build-753ceef.0 → 2.23.2-dev-build-e996ffb.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/README.md +2 -24
- package/dist/package.json +1 -2
- package/dist/src/analyze/command.js +2 -8
- package/dist/src/analyze/select/command.js +9 -13
- package/dist/src/analyze/select/tui/App.js +4 -1
- package/dist/src/analyze/select-agent/command.js +11 -14
- package/dist/src/apply/api-client.d.ts +5 -5
- package/dist/src/apply/api-client.js +8 -18
- package/dist/src/apply/command.d.ts +1 -1
- package/dist/src/apply/command.js +77 -81
- package/dist/src/apply/preview-utils.d.ts +5 -1
- package/dist/src/apply/preview-utils.js +5 -1
- package/dist/src/apply/tui/ServerApplyView.d.ts +6 -3
- package/dist/src/apply/tui/ServerApplyView.js +15 -6
- package/dist/src/apply/tui/ServerPreviewView.d.ts +2 -1
- package/dist/src/apply/tui/ServerPreviewView.js +3 -3
- package/dist/src/generate/command.js +9 -15
- package/dist/src/generate/edit/command.js +0 -1
- package/dist/src/import/command.js +6 -1
- package/dist/src/import/orchestrator.d.ts +1 -0
- package/dist/src/import/orchestrator.js +14 -18
- package/dist/src/import/tui/WizardApp.d.ts +2 -1
- package/dist/src/import/tui/WizardApp.js +8 -8
- package/dist/src/import/tui/final-review-host.d.ts +2 -1
- package/dist/src/import/tui/final-review-host.js +2 -2
- package/dist/src/import/tui/runLivePreview.d.ts +3 -0
- package/dist/src/import/tui/runLivePreview.js +4 -1
- package/dist/src/import/tui/steps/GenerateReviewStep.d.ts +2 -1
- package/dist/src/import/tui/steps/GenerateReviewStep.js +3 -3
- package/dist/src/import/tui/steps/WizardPreviewStep.d.ts +6 -2
- package/dist/src/import/tui/steps/WizardPreviewStep.js +12 -3
- package/dist/src/import/tui/useFinalizePreview.d.ts +2 -0
- package/dist/src/import/tui/useFinalizePreview.js +0 -0
- package/dist/src/import/tui/useLivePreview.d.ts +2 -0
- package/dist/src/import/tui/useLivePreview.js +1 -0
- package/dist/src/index.js +1 -6
- package/dist/src/lib/command-options.d.ts +1 -0
- package/dist/src/lib/command-options.js +3 -0
- package/dist/src/print/command.js +13 -16
- package/dist/src/program.js +1 -8
- package/dist/src/runs/modify-launcher.d.ts +2 -0
- package/dist/src/runs/modify-launcher.js +2 -0
- package/dist/src/runs/push-helpers.d.ts +1 -0
- package/dist/src/runs/push-helpers.js +3 -0
- package/dist/src/runs/replay-helpers.d.ts +4 -0
- package/dist/src/runs/replay-helpers.js +3 -0
- package/package.json +5 -6
- package/dist/src/analytics/apply.d.ts +0 -6
- package/dist/src/analytics/apply.js +0 -30
- package/dist/src/analytics/client.d.ts +0 -7
- package/dist/src/analytics/client.js +0 -68
- package/dist/src/analytics/constants.d.ts +0 -4
- package/dist/src/analytics/constants.js +0 -4
- package/dist/src/analytics/env.d.ts +0 -4
- package/dist/src/analytics/env.js +0 -14
- package/dist/src/analytics/exit.d.ts +0 -5
- package/dist/src/analytics/exit.js +0 -24
- package/dist/src/analytics/index.d.ts +0 -10
- package/dist/src/analytics/index.js +0 -9
- package/dist/src/analytics/normalize.d.ts +0 -3
- package/dist/src/analytics/normalize.js +0 -18
- package/dist/src/analytics/os.d.ts +0 -2
- package/dist/src/analytics/os.js +0 -13
- package/dist/src/analytics/session.d.ts +0 -3
- package/dist/src/analytics/session.js +0 -15
- package/dist/src/analytics/tracker.d.ts +0 -17
- package/dist/src/analytics/tracker.js +0 -126
- package/dist/src/analytics/types.d.ts +0 -28
- package/dist/src/analytics/types.js +0 -1
|
@@ -8,10 +8,9 @@ import { validateDTCGTokenFile } from './validate/validators/dtcg-validator.js';
|
|
|
8
8
|
import { formatDiagnostics } from './validate/validators/format-errors.js';
|
|
9
9
|
import { ValidateView } from './validate/tui/ValidateView.js';
|
|
10
10
|
import { getInteractiveTerminalSupport } from '../lib/terminal-capabilities.js';
|
|
11
|
-
|
|
12
|
-
async function die(message) {
|
|
11
|
+
function die(message) {
|
|
13
12
|
process.stderr.write(`${message}\n`);
|
|
14
|
-
|
|
13
|
+
process.exit(1);
|
|
15
14
|
}
|
|
16
15
|
async function pathExists(p) {
|
|
17
16
|
return access(p)
|
|
@@ -22,16 +21,16 @@ async function assertOutIsNotDirectory(outPath) {
|
|
|
22
21
|
if (await pathExists(outPath)) {
|
|
23
22
|
const s = await stat(outPath);
|
|
24
23
|
if (s.isDirectory())
|
|
25
|
-
|
|
24
|
+
die(`Error: --out must be a file path, not a directory: ${outPath}`);
|
|
26
25
|
}
|
|
27
26
|
}
|
|
28
|
-
|
|
27
|
+
function resolveSession(sessionFlag, command) {
|
|
29
28
|
const db = openPipelineDb();
|
|
30
29
|
try {
|
|
31
30
|
const sessionId = sessionFlag ?? findLatestSessionForCommand(db, command);
|
|
32
31
|
if (!sessionId) {
|
|
33
32
|
const hint = command === 'generate components' ? 'generate components' : 'generate tokens';
|
|
34
|
-
|
|
33
|
+
die(`Error: no completed ${hint} session found. Run ${hint} first, or pass --session <id>.`);
|
|
35
34
|
}
|
|
36
35
|
return sessionId;
|
|
37
36
|
}
|
|
@@ -86,8 +85,7 @@ export function registerPrintCommand(program) {
|
|
|
86
85
|
.action(async (opts) => {
|
|
87
86
|
const outPath = resolve(opts.out);
|
|
88
87
|
await assertOutIsNotDirectory(outPath);
|
|
89
|
-
const sessionId =
|
|
90
|
-
await bindAnalyticsSessionId(sessionId);
|
|
88
|
+
const sessionId = resolveSession(opts.session, 'generate components');
|
|
91
89
|
const db = openPipelineDb();
|
|
92
90
|
let components;
|
|
93
91
|
let generateStepStatus = null;
|
|
@@ -112,13 +110,13 @@ export function registerPrintCommand(program) {
|
|
|
112
110
|
// component was rejected or left unresolved. This is a legitimate
|
|
113
111
|
// "clear the space" intent, but it's destructive, so require --allow-empty.
|
|
114
112
|
if (!opts.allowEmpty) {
|
|
115
|
-
|
|
113
|
+
die(`Error: all ${rejectedCount} generated component${rejectedCount === 1 ? ' was' : 's were'} rejected or left unresolved at final review in session '${sessionId}', so there is nothing to save. Accept at least one component (press [a] on a row, or [A] to accept all), or pass --allow-empty to write an empty manifest that will DELETE all components from the target space on push.`);
|
|
116
114
|
}
|
|
117
115
|
// Fall through: write an empty-but-present components manifest so a
|
|
118
116
|
// subsequent push removes every component from the target space.
|
|
119
117
|
}
|
|
120
118
|
else {
|
|
121
|
-
|
|
119
|
+
die(`Error: no generated components in session '${sessionId}'. Run generate components first.`);
|
|
122
120
|
}
|
|
123
121
|
}
|
|
124
122
|
if (generateStepStatus === 'failed') {
|
|
@@ -147,8 +145,7 @@ export function registerPrintCommand(program) {
|
|
|
147
145
|
.action(async (opts) => {
|
|
148
146
|
const outPath = resolve(opts.out);
|
|
149
147
|
await assertOutIsNotDirectory(outPath);
|
|
150
|
-
const sessionId =
|
|
151
|
-
await bindAnalyticsSessionId(sessionId);
|
|
148
|
+
const sessionId = resolveSession(opts.session, 'generate tokens');
|
|
152
149
|
const db = openPipelineDb();
|
|
153
150
|
let result;
|
|
154
151
|
try {
|
|
@@ -158,7 +155,7 @@ export function registerPrintCommand(program) {
|
|
|
158
155
|
db.close();
|
|
159
156
|
}
|
|
160
157
|
if (result.tokens.length === 0) {
|
|
161
|
-
|
|
158
|
+
die(`Error: no generated tokens in session '${sessionId}'. Run generate tokens first.`);
|
|
162
159
|
}
|
|
163
160
|
const tree = rebuildDTCGTree(result.groups, result.tokens);
|
|
164
161
|
await mkdir(resolve(outPath, '..'), { recursive: true });
|
|
@@ -174,7 +171,7 @@ export function registerPrintCommand(program) {
|
|
|
174
171
|
.action(async (opts) => {
|
|
175
172
|
if (!opts.components && !opts.tokens) {
|
|
176
173
|
process.stderr.write('Error: at least one of --components or --tokens is required.\n\nUsage: print validate [--components <path>] [--tokens <path>]\n');
|
|
177
|
-
|
|
174
|
+
process.exit(1);
|
|
178
175
|
}
|
|
179
176
|
const viewResults = [];
|
|
180
177
|
if (opts.components) {
|
|
@@ -202,7 +199,7 @@ export function registerPrintCommand(program) {
|
|
|
202
199
|
if (getInteractiveTerminalSupport().supported) {
|
|
203
200
|
const { waitUntilExit } = render(createElement(ValidateView, {
|
|
204
201
|
results: viewResults,
|
|
205
|
-
onExit: () =>
|
|
202
|
+
onExit: () => process.exit(exitCode),
|
|
206
203
|
}));
|
|
207
204
|
await waitUntilExit();
|
|
208
205
|
}
|
|
@@ -215,7 +212,7 @@ export function registerPrintCommand(program) {
|
|
|
215
212
|
}))
|
|
216
213
|
.join('\n\n');
|
|
217
214
|
process.stdout.write(output + '\n');
|
|
218
|
-
|
|
215
|
+
process.exit(exitCode);
|
|
219
216
|
}
|
|
220
217
|
});
|
|
221
218
|
}
|
package/dist/src/program.js
CHANGED
|
@@ -12,7 +12,6 @@ import { registerImportCommand } from './import/command.js';
|
|
|
12
12
|
import { registerSetupCommand } from './setup/command.js';
|
|
13
13
|
import { registerRunsCommand } from './runs/ls-command.js';
|
|
14
14
|
import { beginCommand } from './lib/debug-preamble.js';
|
|
15
|
-
import { completeActiveCommand, flushAnalytics, noteCommandStart } from './analytics/index.js';
|
|
16
15
|
const require = createRequire(import.meta.url);
|
|
17
16
|
const pkg = require('../package.json');
|
|
18
17
|
/**
|
|
@@ -90,13 +89,7 @@ export function createProgram() {
|
|
|
90
89
|
const chain = [];
|
|
91
90
|
for (let c = actionCommand; c && c.parent; c = c.parent)
|
|
92
91
|
chain.unshift(c.name());
|
|
93
|
-
|
|
94
|
-
noteCommandStart(commandChain);
|
|
95
|
-
await beginCommand(commandChain, { ...(debug !== undefined ? { debug } : {}) });
|
|
96
|
-
});
|
|
97
|
-
program.hook('postAction', async () => {
|
|
98
|
-
await completeActiveCommand();
|
|
99
|
-
await flushAnalytics();
|
|
92
|
+
await beginCommand(chain.join(' ') || actionCommand.name(), { ...(debug !== undefined ? { debug } : {}) });
|
|
100
93
|
});
|
|
101
94
|
return program;
|
|
102
95
|
}
|
|
@@ -26,5 +26,7 @@ export type ModifyLauncherInput = {
|
|
|
26
26
|
initialHost?: string;
|
|
27
27
|
/** Pre-fill CMA token (from credentials.json / env). */
|
|
28
28
|
initialCmaToken?: string;
|
|
29
|
+
/** From `--allow-deletions` flag. Forwarded to wizard's push step. */
|
|
30
|
+
allowDeletions?: boolean;
|
|
29
31
|
};
|
|
30
32
|
export declare function launchModifyWizard(input: ModifyLauncherInput): Promise<void>;
|
|
@@ -35,6 +35,8 @@ export async function launchModifyWizard(input) {
|
|
|
35
35
|
props.initialHost = input.initialHost;
|
|
36
36
|
if (input.initialCmaToken)
|
|
37
37
|
props.initialCmaToken = input.initialCmaToken;
|
|
38
|
+
if (input.allowDeletions !== undefined)
|
|
39
|
+
props.allowDeletions = input.allowDeletions;
|
|
38
40
|
const { waitUntilExit } = render(createElement(WizardApp, props));
|
|
39
41
|
await waitUntilExit();
|
|
40
42
|
}
|
|
@@ -16,6 +16,8 @@ export type ReplayRunOptions = {
|
|
|
16
16
|
interactive?: boolean;
|
|
17
17
|
/** When true, bypass the source/saved-file staleness check. */
|
|
18
18
|
force?: boolean;
|
|
19
|
+
/** From `--allow-deletions` flag. Forwarded verbatim to the pushed session's apply request. */
|
|
20
|
+
allowDeletions?: boolean;
|
|
19
21
|
/**
|
|
20
22
|
* Test seam: replace the interactive prompt with a deterministic resolver.
|
|
21
23
|
* The CLI surface never sets this; only used by tests.
|
|
@@ -57,6 +59,8 @@ export type ModifyRunOptions = {
|
|
|
57
59
|
outDir?: string;
|
|
58
60
|
/** When true, bypass the source/saved-file staleness check. */
|
|
59
61
|
force?: boolean;
|
|
62
|
+
/** From `--allow-deletions` flag. Forwarded through the modify wizard's push step. */
|
|
63
|
+
allowDeletions?: boolean;
|
|
60
64
|
};
|
|
61
65
|
/**
|
|
62
66
|
* Re-open the wizard with a prior run's extract/generate session pre-populated
|
|
@@ -83,6 +83,7 @@ export async function replayRun(opts) {
|
|
|
83
83
|
environmentId,
|
|
84
84
|
cmaToken,
|
|
85
85
|
...(host ? { host } : {}),
|
|
86
|
+
...(opts.allowDeletions ? { allowDeletions: true } : {}),
|
|
86
87
|
});
|
|
87
88
|
if (!result.ok) {
|
|
88
89
|
throw new Error(result.error);
|
|
@@ -98,6 +99,7 @@ export async function replayRun(opts) {
|
|
|
98
99
|
environmentId,
|
|
99
100
|
cmaToken,
|
|
100
101
|
...(host ? { host } : {}),
|
|
102
|
+
...(opts.allowDeletions ? { allowDeletions: true } : {}),
|
|
101
103
|
});
|
|
102
104
|
if (!tokenResult.ok) {
|
|
103
105
|
throw new Error(tokenResult.error);
|
|
@@ -157,5 +159,6 @@ export async function modifyRun(opts) {
|
|
|
157
159
|
...(mergedEnvironmentId ? { initialEnvironmentId: mergedEnvironmentId } : {}),
|
|
158
160
|
...(mergedHost ? { initialHost: mergedHost } : {}),
|
|
159
161
|
...(mergedCmaToken ? { initialCmaToken: mergedCmaToken } : {}),
|
|
162
|
+
...(opts.allowDeletions !== undefined ? { allowDeletions: opts.allowDeletions } : {}),
|
|
160
163
|
});
|
|
161
164
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentful/experience-design-system-cli",
|
|
3
|
-
"version": "2.23.2-dev-build-
|
|
3
|
+
"version": "2.23.2-dev-build-e996ffb.0",
|
|
4
4
|
"description": "Contentful Experiences design system import CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -28,16 +28,15 @@
|
|
|
28
28
|
"prompts/"
|
|
29
29
|
],
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@segment/analytics-node": "^3.0.0",
|
|
32
31
|
"commander": "^13.1.0",
|
|
33
32
|
"ink": "^4.4.1",
|
|
34
33
|
"react": "^18.3.1",
|
|
35
34
|
"react-devtools-core": "^4.19.1",
|
|
36
35
|
"react-dom": "^18.3.1",
|
|
37
|
-
"@contentful/experience-design-system-client": "2.23.2-dev-build-
|
|
38
|
-
"@contentful/experience-design-system-
|
|
39
|
-
"@contentful/experience-design-system-
|
|
40
|
-
"@contentful/experience-design-system-
|
|
36
|
+
"@contentful/experience-design-system-client": "2.23.2-dev-build-e996ffb.0",
|
|
37
|
+
"@contentful/experience-design-system-generation": "2.23.2-dev-build-e996ffb.0",
|
|
38
|
+
"@contentful/experience-design-system-extraction": "2.23.2-dev-build-e996ffb.0",
|
|
39
|
+
"@contentful/experience-design-system-types": "2.23.2-dev-build-e996ffb.0"
|
|
41
40
|
},
|
|
42
41
|
"devDependencies": {
|
|
43
42
|
"@tsconfig/node24": "^24.0.4",
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { ApplyOperationResponse } from '@contentful/experience-design-system-types';
|
|
2
|
-
import type { ImportApiClient } from '../apply/api-client.js';
|
|
3
|
-
/** Record apply/preview API outcomes on the active command. */
|
|
4
|
-
export declare function recordApplyOutcome(client: ImportApiClient, spaceId: string, environmentId: string, operation: ApplyOperationResponse): void;
|
|
5
|
-
/** Record Contentful target context without an apply operation (e.g. preview-only). */
|
|
6
|
-
export declare function recordContentfulContext(client: ImportApiClient, spaceId: string, environmentId: string): void;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { enrichCommandResult, setCommandContext } from './tracker.js';
|
|
2
|
-
function countWriteResult(items, entityType) {
|
|
3
|
-
const subset = items.filter((item) => item.entityType === entityType);
|
|
4
|
-
return {
|
|
5
|
-
created_count: subset.filter((item) => item.action === 'create' && item.status === 'succeeded').length,
|
|
6
|
-
updated_count: subset.filter((item) => item.action === 'update' && item.status === 'succeeded').length,
|
|
7
|
-
failed_count: subset.filter((item) => item.status === 'failed').length,
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
/** Record apply/preview API outcomes on the active command. */
|
|
11
|
-
export function recordApplyOutcome(client, spaceId, environmentId, operation) {
|
|
12
|
-
setCommandContext({
|
|
13
|
-
space_key: spaceId,
|
|
14
|
-
environment_key: environmentId,
|
|
15
|
-
x_contentful_request_id: client.getLastRequestId(),
|
|
16
|
-
});
|
|
17
|
-
enrichCommandResult({
|
|
18
|
-
dsi_operation_id: operation.sys.id,
|
|
19
|
-
component_type_result: countWriteResult(operation.items ?? [], 'ComponentType'),
|
|
20
|
-
design_token_result: countWriteResult(operation.items ?? [], 'DesignToken'),
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
/** Record Contentful target context without an apply operation (e.g. preview-only). */
|
|
24
|
-
export function recordContentfulContext(client, spaceId, environmentId) {
|
|
25
|
-
setCommandContext({
|
|
26
|
-
space_key: spaceId,
|
|
27
|
-
environment_key: environmentId,
|
|
28
|
-
x_contentful_request_id: client.getLastRequestId(),
|
|
29
|
-
});
|
|
30
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export declare function cliVersion(): string;
|
|
2
|
-
export declare function analyticsEnabled(): boolean;
|
|
3
|
-
export declare function trackEvent(event: string, properties: Record<string, unknown>, anonymousId: string, options?: {
|
|
4
|
-
flush?: boolean;
|
|
5
|
-
}): Promise<void>;
|
|
6
|
-
export declare function flushAnalytics(): Promise<void>;
|
|
7
|
-
export declare function resetAnalyticsClientForTests(): void;
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { createRequire } from 'node:module';
|
|
2
|
-
import { Analytics } from '@segment/analytics-node';
|
|
3
|
-
const require = createRequire(import.meta.url);
|
|
4
|
-
const pkg = require('../../package.json');
|
|
5
|
-
// Anonymous usage telemetry for the CLI. Disabled when DISABLE_ANALYTICS is set
|
|
6
|
-
// or when no write key is configured. Never blocks command execution.
|
|
7
|
-
let analyticsClient = null;
|
|
8
|
-
export function cliVersion() {
|
|
9
|
-
return pkg.version;
|
|
10
|
-
}
|
|
11
|
-
export function analyticsEnabled() {
|
|
12
|
-
return !process.env.DISABLE_ANALYTICS && Boolean(resolveWriteKey());
|
|
13
|
-
}
|
|
14
|
-
function resolveWriteKey() {
|
|
15
|
-
const key = (process.env.SEGMENT_WRITE_KEY ?? '').trim();
|
|
16
|
-
return key.length > 0 ? key : undefined;
|
|
17
|
-
}
|
|
18
|
-
function getClient() {
|
|
19
|
-
if (!analyticsEnabled())
|
|
20
|
-
return null;
|
|
21
|
-
const writeKey = resolveWriteKey();
|
|
22
|
-
if (!writeKey)
|
|
23
|
-
return null;
|
|
24
|
-
if (!analyticsClient) {
|
|
25
|
-
analyticsClient = new Analytics({ writeKey });
|
|
26
|
-
analyticsClient.on('error', () => {
|
|
27
|
-
/* never block the CLI on telemetry errors */
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
return analyticsClient;
|
|
31
|
-
}
|
|
32
|
-
export async function trackEvent(event, properties, anonymousId, options) {
|
|
33
|
-
const client = getClient();
|
|
34
|
-
if (!client)
|
|
35
|
-
return;
|
|
36
|
-
try {
|
|
37
|
-
client.track({
|
|
38
|
-
event,
|
|
39
|
-
properties,
|
|
40
|
-
anonymousId,
|
|
41
|
-
timestamp: new Date(),
|
|
42
|
-
});
|
|
43
|
-
if (options?.flush)
|
|
44
|
-
await flushAnalytics();
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
// Telemetry must never affect CLI exit codes or output.
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
// CLI processes are short-lived — we flush (and recreate the client) after each
|
|
51
|
-
// event so terminal telemetry survives process.exit. Do not "optimize" this into
|
|
52
|
-
// a deferred batch flush on process exit; Node will not await async exit hooks.
|
|
53
|
-
export async function flushAnalytics() {
|
|
54
|
-
if (!analyticsClient)
|
|
55
|
-
return;
|
|
56
|
-
try {
|
|
57
|
-
await analyticsClient.closeAndFlush();
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
// Swallow — telemetry must never affect CLI behavior.
|
|
61
|
-
}
|
|
62
|
-
finally {
|
|
63
|
-
analyticsClient = null;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
export function resetAnalyticsClientForTests() {
|
|
67
|
-
analyticsClient = null;
|
|
68
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/** Parent pipeline session id propagated to orchestrator subprocesses. */
|
|
2
|
-
export declare const ANALYTICS_SESSION_ENV = "EDS_ANALYTICS_SESSION_ID";
|
|
3
|
-
/** Set when a command is spawned by the import orchestrator. */
|
|
4
|
-
export declare const IMPORT_PIPELINE_ENV = "EDS_IMPORT_PIPELINE";
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
/** Merge pipeline analytics env into a subprocess environment. */
|
|
2
|
-
export declare function analyticsEnvForSubprocess(env: NodeJS.ProcessEnv, analyticsSessionId: string): NodeJS.ProcessEnv;
|
|
3
|
-
/** Debug + pipeline analytics env for orchestrator subprocesses. */
|
|
4
|
-
export declare function pipelineSubprocessEnv(env: NodeJS.ProcessEnv, analyticsSessionId: string): NodeJS.ProcessEnv;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { debugEnvForSubprocess } from '../lib/debug-logger.js';
|
|
2
|
-
import { ANALYTICS_SESSION_ENV, IMPORT_PIPELINE_ENV } from './constants.js';
|
|
3
|
-
/** Merge pipeline analytics env into a subprocess environment. */
|
|
4
|
-
export function analyticsEnvForSubprocess(env, analyticsSessionId) {
|
|
5
|
-
return {
|
|
6
|
-
...env,
|
|
7
|
-
[IMPORT_PIPELINE_ENV]: '1',
|
|
8
|
-
[ANALYTICS_SESSION_ENV]: analyticsSessionId,
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
/** Debug + pipeline analytics env for orchestrator subprocesses. */
|
|
12
|
-
export function pipelineSubprocessEnv(env, analyticsSessionId) {
|
|
13
|
-
return analyticsEnvForSubprocess(debugEnvForSubprocess(env), analyticsSessionId);
|
|
14
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { ApiError } from '../apply/api-client.js';
|
|
2
|
-
import type { CommandFailure } from './types.js';
|
|
3
|
-
export declare function exitWithAnalytics(code: number, fields?: CommandFailure): Promise<never>;
|
|
4
|
-
export declare function failureFromApiError(error: ApiError): CommandFailure;
|
|
5
|
-
export declare function failureFromUnknown(error: unknown): CommandFailure;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { flushAnalytics } from './client.js';
|
|
2
|
-
import { completeActiveCommand, failActiveCommand } from './tracker.js';
|
|
3
|
-
export async function exitWithAnalytics(code, fields = {}) {
|
|
4
|
-
if (code === 0)
|
|
5
|
-
await completeActiveCommand();
|
|
6
|
-
else
|
|
7
|
-
await failActiveCommand({ exit_code: code, ...fields });
|
|
8
|
-
await flushAnalytics();
|
|
9
|
-
process.exit(code);
|
|
10
|
-
throw new Error('unreachable');
|
|
11
|
-
}
|
|
12
|
-
export function failureFromApiError(error) {
|
|
13
|
-
return {
|
|
14
|
-
error_name: error.name,
|
|
15
|
-
http_status_code: error.status,
|
|
16
|
-
exit_code: 1,
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
export function failureFromUnknown(error) {
|
|
20
|
-
if (error instanceof Error) {
|
|
21
|
-
return { error_name: error.name, exit_code: 1 };
|
|
22
|
-
}
|
|
23
|
-
return { error_name: 'Error', exit_code: 1 };
|
|
24
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export { ANALYTICS_SESSION_ENV, IMPORT_PIPELINE_ENV } from './constants.js';
|
|
2
|
-
export { analyticsEnvForSubprocess, pipelineSubprocessEnv } from './env.js';
|
|
3
|
-
export { exitWithAnalytics, failureFromApiError, failureFromUnknown } from './exit.js';
|
|
4
|
-
export { analyticsEnabled, cliVersion, flushAnalytics, resetAnalyticsClientForTests, trackEvent } from './client.js';
|
|
5
|
-
export { isPipelineAnalyticsChild, resolveAnalyticsSessionId } from './session.js';
|
|
6
|
-
export { normalizeCommand } from './normalize.js';
|
|
7
|
-
export { getOsName } from './os.js';
|
|
8
|
-
export { bindAnalyticsSession, bindAnalyticsSessionId, completeActiveCommand, emitSessionStarted, enrichCommandResult, failActiveCommand, getBoundSessionId, noteCommandStart, resetAnalyticsStateForTests, setCommandContext, } from './tracker.js';
|
|
9
|
-
export { recordApplyOutcome, recordContentfulContext } from './apply.js';
|
|
10
|
-
export type { CommandCompletion, CommandContext, CommandFailure, DsiCliCommand, EntryCommand, OsName, WriteResult, } from './types.js';
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export { ANALYTICS_SESSION_ENV, IMPORT_PIPELINE_ENV } from './constants.js';
|
|
2
|
-
export { analyticsEnvForSubprocess, pipelineSubprocessEnv } from './env.js';
|
|
3
|
-
export { exitWithAnalytics, failureFromApiError, failureFromUnknown } from './exit.js';
|
|
4
|
-
export { analyticsEnabled, cliVersion, flushAnalytics, resetAnalyticsClientForTests, trackEvent } from './client.js';
|
|
5
|
-
export { isPipelineAnalyticsChild, resolveAnalyticsSessionId } from './session.js';
|
|
6
|
-
export { normalizeCommand } from './normalize.js';
|
|
7
|
-
export { getOsName } from './os.js';
|
|
8
|
-
export { bindAnalyticsSession, bindAnalyticsSessionId, completeActiveCommand, emitSessionStarted, enrichCommandResult, failActiveCommand, getBoundSessionId, noteCommandStart, resetAnalyticsStateForTests, setCommandContext, } from './tracker.js';
|
|
9
|
-
export { recordApplyOutcome, recordContentfulContext } from './apply.js';
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
const COMMAND_MAP = {
|
|
2
|
-
'analyze extract': 'analyze_extract',
|
|
3
|
-
'analyze select': 'analyze_select',
|
|
4
|
-
'analyze select-agent': 'analyze_select',
|
|
5
|
-
'generate components': 'generate_components',
|
|
6
|
-
'generate tokens': 'generate_tokens',
|
|
7
|
-
'generate edit': 'generate_edit',
|
|
8
|
-
'apply preview': 'apply_preview',
|
|
9
|
-
'apply select': 'apply_select',
|
|
10
|
-
'apply push': 'apply_push',
|
|
11
|
-
'print components': 'print_components',
|
|
12
|
-
'print tokens': 'print_tokens',
|
|
13
|
-
import: 'import',
|
|
14
|
-
};
|
|
15
|
-
/** Map a Commander command chain (e.g. "apply push") to a tracked command id, if any. */
|
|
16
|
-
export function normalizeCommand(commandChain) {
|
|
17
|
-
return COMMAND_MAP[commandChain];
|
|
18
|
-
}
|
package/dist/src/analytics/os.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
const OS_NAMES = {
|
|
2
|
-
android: 'Android',
|
|
3
|
-
aix: 'Linux',
|
|
4
|
-
darwin: 'macOS',
|
|
5
|
-
freebsd: 'Linux',
|
|
6
|
-
linux: 'Linux',
|
|
7
|
-
openbsd: 'Linux',
|
|
8
|
-
sunos: 'Linux',
|
|
9
|
-
win32: 'Windows',
|
|
10
|
-
};
|
|
11
|
-
export function getOsName() {
|
|
12
|
-
return OS_NAMES[process.platform] ?? 'other';
|
|
13
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { generateSessionId } from '../session/session-id.js';
|
|
2
|
-
import { ANALYTICS_SESSION_ENV } from './constants.js';
|
|
3
|
-
/** Prefer the pipeline parent session, then an explicit id, then a new slug. */
|
|
4
|
-
export function resolveAnalyticsSessionId(explicit) {
|
|
5
|
-
const inherited = process.env[ANALYTICS_SESSION_ENV]?.trim();
|
|
6
|
-
if (inherited)
|
|
7
|
-
return inherited;
|
|
8
|
-
const passed = explicit?.trim();
|
|
9
|
-
if (passed)
|
|
10
|
-
return passed;
|
|
11
|
-
return generateSessionId();
|
|
12
|
-
}
|
|
13
|
-
export function isPipelineAnalyticsChild() {
|
|
14
|
-
return Boolean(process.env[ANALYTICS_SESSION_ENV]?.trim());
|
|
15
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { CommandCompletion, CommandContext, CommandFailure, EntryCommand } from './types.js';
|
|
2
|
-
/** Record the start of a tracked command. Invoked is deferred until a session is bound. */
|
|
3
|
-
export declare function noteCommandStart(commandChain: string): void;
|
|
4
|
-
/** Bind a session id, preferring a pipeline parent id when present. */
|
|
5
|
-
export declare function bindAnalyticsSessionId(sessionId: string | undefined, context?: CommandContext): Promise<string>;
|
|
6
|
-
/** Attach Contentful target context for the active command. */
|
|
7
|
-
export declare function setCommandContext(context: CommandContext): void;
|
|
8
|
-
/** Merge optional completion fields before the terminal event fires. */
|
|
9
|
-
export declare function enrichCommandResult(fields: CommandCompletion): void;
|
|
10
|
-
export declare function getBoundSessionId(): string | undefined;
|
|
11
|
-
/** Bind the pipeline session and emit invoked once both command and session are known. */
|
|
12
|
-
export declare function bindAnalyticsSession(id: string, context?: CommandContext): Promise<void>;
|
|
13
|
-
/** Emit session_started once per new pipeline head. */
|
|
14
|
-
export declare function emitSessionStarted(entryCommand: EntryCommand): Promise<void>;
|
|
15
|
-
export declare function completeActiveCommand(): Promise<void>;
|
|
16
|
-
export declare function failActiveCommand(fields?: CommandFailure): Promise<void>;
|
|
17
|
-
export declare function resetAnalyticsStateForTests(): void;
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
import { cliVersion, trackEvent } from './client.js';
|
|
2
|
-
import { IMPORT_PIPELINE_ENV } from './constants.js';
|
|
3
|
-
import { normalizeCommand } from './normalize.js';
|
|
4
|
-
import { getOsName } from './os.js';
|
|
5
|
-
import { resolveAnalyticsSessionId } from './session.js';
|
|
6
|
-
let pending = null;
|
|
7
|
-
let sessionId;
|
|
8
|
-
let sessionStartedEmitted = false;
|
|
9
|
-
function isPipelineStep() {
|
|
10
|
-
return process.env[IMPORT_PIPELINE_ENV] === '1';
|
|
11
|
-
}
|
|
12
|
-
function buildBaseProps(command) {
|
|
13
|
-
return {
|
|
14
|
-
dsi_session_id: sessionId,
|
|
15
|
-
command,
|
|
16
|
-
...(isPipelineStep() ? { is_pipeline_step: true } : {}),
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
function mergeContext(target, source) {
|
|
20
|
-
if (source.space_key !== undefined)
|
|
21
|
-
target.space_key = source.space_key;
|
|
22
|
-
if (source.environment_key !== undefined)
|
|
23
|
-
target.environment_key = source.environment_key;
|
|
24
|
-
if (source.x_contentful_request_id !== undefined) {
|
|
25
|
-
target.x_contentful_request_id = source.x_contentful_request_id;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
/** Record the start of a tracked command. Invoked is deferred until a session is bound. */
|
|
29
|
-
export function noteCommandStart(commandChain) {
|
|
30
|
-
const command = normalizeCommand(commandChain);
|
|
31
|
-
if (!command)
|
|
32
|
-
return;
|
|
33
|
-
pending = {
|
|
34
|
-
command,
|
|
35
|
-
startedAt: Date.now(),
|
|
36
|
-
invoked: false,
|
|
37
|
-
terminalEmitted: false,
|
|
38
|
-
context: {},
|
|
39
|
-
completion: {},
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
/** Bind a session id, preferring a pipeline parent id when present. */
|
|
43
|
-
export async function bindAnalyticsSessionId(sessionId, context) {
|
|
44
|
-
const id = resolveAnalyticsSessionId(sessionId);
|
|
45
|
-
await bindAnalyticsSession(id, context);
|
|
46
|
-
return id;
|
|
47
|
-
}
|
|
48
|
-
/** Attach Contentful target context for the active command. */
|
|
49
|
-
export function setCommandContext(context) {
|
|
50
|
-
if (!pending)
|
|
51
|
-
return;
|
|
52
|
-
mergeContext(pending.context, context);
|
|
53
|
-
mergeContext(pending.completion, context);
|
|
54
|
-
}
|
|
55
|
-
/** Merge optional completion fields before the terminal event fires. */
|
|
56
|
-
export function enrichCommandResult(fields) {
|
|
57
|
-
if (!pending)
|
|
58
|
-
return;
|
|
59
|
-
Object.assign(pending.completion, fields);
|
|
60
|
-
mergeContext(pending.context, fields);
|
|
61
|
-
}
|
|
62
|
-
export function getBoundSessionId() {
|
|
63
|
-
return sessionId;
|
|
64
|
-
}
|
|
65
|
-
/** Bind the pipeline session and emit invoked once both command and session are known. */
|
|
66
|
-
export async function bindAnalyticsSession(id, context) {
|
|
67
|
-
sessionId = id;
|
|
68
|
-
if (context)
|
|
69
|
-
setCommandContext(context);
|
|
70
|
-
await emitInvokedIfReady();
|
|
71
|
-
}
|
|
72
|
-
/** Emit session_started once per new pipeline head. */
|
|
73
|
-
export async function emitSessionStarted(entryCommand) {
|
|
74
|
-
if (!sessionId || sessionStartedEmitted)
|
|
75
|
-
return;
|
|
76
|
-
sessionStartedEmitted = true;
|
|
77
|
-
await trackEvent('dsi_cli_session_started', {
|
|
78
|
-
dsi_session_id: sessionId,
|
|
79
|
-
entry_command: entryCommand,
|
|
80
|
-
cli_version: cliVersion(),
|
|
81
|
-
node_version: process.version,
|
|
82
|
-
os_name: getOsName(),
|
|
83
|
-
}, sessionId, { flush: true });
|
|
84
|
-
await emitInvokedIfReady();
|
|
85
|
-
}
|
|
86
|
-
async function emitInvokedIfReady() {
|
|
87
|
-
if (!pending || pending.invoked || !sessionId)
|
|
88
|
-
return;
|
|
89
|
-
pending.invoked = true;
|
|
90
|
-
await trackEvent('dsi_cli_command_invoked', {
|
|
91
|
-
...buildBaseProps(pending.command),
|
|
92
|
-
...pending.context,
|
|
93
|
-
}, sessionId, { flush: true });
|
|
94
|
-
}
|
|
95
|
-
export async function completeActiveCommand() {
|
|
96
|
-
if (!pending || pending.terminalEmitted || !sessionId || !pending.invoked)
|
|
97
|
-
return;
|
|
98
|
-
pending.terminalEmitted = true;
|
|
99
|
-
const durationMs = Date.now() - pending.startedAt;
|
|
100
|
-
await trackEvent('dsi_cli_command_completed', {
|
|
101
|
-
...buildBaseProps(pending.command),
|
|
102
|
-
...pending.context,
|
|
103
|
-
...pending.completion,
|
|
104
|
-
outcome: 'ok',
|
|
105
|
-
duration_ms: durationMs,
|
|
106
|
-
}, sessionId, { flush: true });
|
|
107
|
-
}
|
|
108
|
-
export async function failActiveCommand(fields = {}) {
|
|
109
|
-
if (!pending || pending.terminalEmitted || !sessionId || !pending.invoked)
|
|
110
|
-
return;
|
|
111
|
-
pending.terminalEmitted = true;
|
|
112
|
-
const durationMs = Date.now() - pending.startedAt;
|
|
113
|
-
const outcome = fields.exit_code === 130 ? 'interrupted' : 'error';
|
|
114
|
-
await trackEvent('dsi_cli_command_failed', {
|
|
115
|
-
...buildBaseProps(pending.command),
|
|
116
|
-
...pending.context,
|
|
117
|
-
...fields,
|
|
118
|
-
outcome,
|
|
119
|
-
duration_ms: durationMs,
|
|
120
|
-
}, sessionId, { flush: true });
|
|
121
|
-
}
|
|
122
|
-
export function resetAnalyticsStateForTests() {
|
|
123
|
-
pending = null;
|
|
124
|
-
sessionId = undefined;
|
|
125
|
-
sessionStartedEmitted = false;
|
|
126
|
-
}
|