@prisma-next/cli-telemetry 0.10.0 → 0.11.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/LICENSE +201 -0
- package/dist/enrich-CGZ8Za8Y.mjs +214 -0
- package/dist/enrich-CGZ8Za8Y.mjs.map +1 -0
- package/dist/exports/index.d.mts +123 -53
- package/dist/exports/index.d.mts.map +1 -1
- package/dist/exports/index.mjs +7 -6
- package/dist/exports/index.mjs.map +1 -1
- package/dist/sender.mjs +10 -170
- package/dist/sender.mjs.map +1 -1
- package/package.json +23 -20
- package/src/enrich.ts +91 -8
- package/src/exports/index.ts +2 -0
- package/src/payload.ts +46 -14
- package/src/sender.ts +1 -1
- package/src/spawn.ts +21 -10
package/src/payload.ts
CHANGED
|
@@ -2,11 +2,29 @@ import { type } from 'arktype';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Wire-shape payload the parent IPC-sends to the forked child sender.
|
|
5
|
-
* Mirrors the fields the parent has naturally in hand at command
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* agent)
|
|
5
|
+
* Mirrors only the fields the parent has naturally in hand at command
|
|
6
|
+
* start: installation id, sanitised command + flags, CLI version, and
|
|
7
|
+
* the project root the child uses to discover everything else. The
|
|
8
|
+
* child probes its own process (runtime/os/arch, package manager, ts
|
|
9
|
+
* version, agent) and reads the user's `prisma-next.config.*` via
|
|
10
|
+
* c12 to derive `databaseTarget` and `extensions`.
|
|
11
|
+
*
|
|
12
|
+
* Loading c12 on the parent side would put a `loadConfig()` await on
|
|
13
|
+
* the command's hot path between gate resolution and `fork()`,
|
|
14
|
+
* opening a race against any CLI command that throws synchronously
|
|
15
|
+
* before that await resolves (the parent exits before forking the
|
|
16
|
+
* sender, and the telemetry event is lost). Moving the load into the
|
|
17
|
+
* detached child eliminates that race; the trade is that the child
|
|
18
|
+
* now evaluates user TS config code, so it's gated behind the same
|
|
19
|
+
* privacy checks the parent already resolved before forking.
|
|
20
|
+
*
|
|
21
|
+
* `databaseTarget` is an optional parent-side override for the
|
|
22
|
+
* c12-derived value: the first-`init` invocation supplies the
|
|
23
|
+
* prompt-chosen target via this field because the config file does
|
|
24
|
+
* not yet exist on disk at that moment. Every other invocation
|
|
25
|
+
* leaves it unset (`undefined`) and the child's c12 load determines
|
|
26
|
+
* the value — there is no third state, so the field's type is
|
|
27
|
+
* `string | undefined`, not `string | null | undefined`.
|
|
10
28
|
*
|
|
11
29
|
* Both sides version-couple on this shape because the IPC carrier is
|
|
12
30
|
* structured-cloned by Node and there's no on-wire compat to maintain.
|
|
@@ -16,12 +34,26 @@ export interface ParentToSenderPayload {
|
|
|
16
34
|
readonly version: string;
|
|
17
35
|
readonly command: string;
|
|
18
36
|
readonly flags: readonly string[];
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Absolute path of the user's project. The child reads
|
|
39
|
+
* `<projectRoot>/package.json` for `tsVersion` and loads
|
|
40
|
+
* `<projectRoot>/prisma-next.config.*` via c12 for `databaseTarget`
|
|
41
|
+
* + `extensions`.
|
|
42
|
+
*/
|
|
22
43
|
readonly projectRoot: string;
|
|
23
44
|
/** Resolved endpoint URL (already includes the `/events` path). */
|
|
24
45
|
readonly endpoint: string;
|
|
46
|
+
/**
|
|
47
|
+
* Optional parent-side override for the c12-derived database target.
|
|
48
|
+
* Set by `fireTelemetryAfterInitConsent` (the first-`init` path,
|
|
49
|
+
* where the config file is about to be written but doesn't exist
|
|
50
|
+
* yet); left undefined by `fireTelemetryFromPreAction` (steady
|
|
51
|
+
* state, child resolves the value via c12). The wire-format
|
|
52
|
+
* `TelemetryEvent.databaseTarget: string | null` keeps `null` as
|
|
53
|
+
* the on-the-wire "no target known" marker, but the IPC override
|
|
54
|
+
* channel only needs two states so it's `string | undefined`.
|
|
55
|
+
*/
|
|
56
|
+
readonly databaseTarget?: string;
|
|
25
57
|
}
|
|
26
58
|
|
|
27
59
|
/**
|
|
@@ -30,10 +62,11 @@ export interface ParentToSenderPayload {
|
|
|
30
62
|
* cannot silently produce a degraded telemetry event downstream.
|
|
31
63
|
*
|
|
32
64
|
* Mirrors the backend's own arktype schema in spirit: required scalars
|
|
33
|
-
* must be non-empty strings; `databaseTarget` is
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
* the
|
|
65
|
+
* must be non-empty strings; the optional `databaseTarget` override is
|
|
66
|
+
* `string` when present (no `null` — see the type's doc-block); the
|
|
67
|
+
* string array is validated element-by-element. Size caps are enforced
|
|
68
|
+
* by the backend, not here — IPC is structured-cloned and the
|
|
69
|
+
* parent/child agree on the schema by version-coupling.
|
|
37
70
|
*/
|
|
38
71
|
const requiredString = type.string.moreThanLength(0);
|
|
39
72
|
const stringArray = type.string.array();
|
|
@@ -43,10 +76,9 @@ export const parentToSenderPayloadSchema = type({
|
|
|
43
76
|
version: requiredString,
|
|
44
77
|
command: requiredString,
|
|
45
78
|
flags: stringArray,
|
|
46
|
-
databaseTarget: type.string.or('null'),
|
|
47
|
-
extensions: stringArray,
|
|
48
79
|
projectRoot: requiredString,
|
|
49
80
|
endpoint: requiredString,
|
|
81
|
+
'databaseTarget?': type.string,
|
|
50
82
|
});
|
|
51
83
|
|
|
52
84
|
export function isParentToSenderPayload(value: unknown): value is ParentToSenderPayload {
|
package/src/sender.ts
CHANGED
|
@@ -33,7 +33,7 @@ function debugLog(message: string, error?: unknown): void {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
async function postEvent(payload: ParentToSenderPayload): Promise<void> {
|
|
36
|
-
const event = buildTelemetryEventFromProcess(payload);
|
|
36
|
+
const event = await buildTelemetryEventFromProcess(payload);
|
|
37
37
|
const controller = new AbortController();
|
|
38
38
|
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
39
39
|
try {
|
package/src/spawn.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { fork } from 'node:child_process';
|
|
2
2
|
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { ifDefined } from '@prisma-next/utils/defined';
|
|
3
4
|
import { resolveTelemetryEndpoint } from './endpoint';
|
|
4
5
|
import { resolveGating } from './gating';
|
|
5
6
|
import type { ParentToSenderPayload } from './payload';
|
|
@@ -8,22 +9,33 @@ import { readUserConfig, type UserConfig } from './user-config';
|
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Inputs the CLI entry point hands the telemetry layer at command
|
|
11
|
-
* start. The CLI is responsible for stitching commander's result
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* `
|
|
12
|
+
* start. The CLI is responsible for stitching commander's result and
|
|
13
|
+
* the project root together; the telemetry module does no I/O of its
|
|
14
|
+
* own except for the user-config read (skipped when `userConfig` is
|
|
15
|
+
* provided). `extensions` is deliberately absent: the detached child
|
|
16
|
+
* loads `prisma-next.config.*` via c12 itself and derives the
|
|
17
|
+
* extension-pack ids from the validated config — see the rationale
|
|
18
|
+
* on `ParentToSenderPayload` for why c12 lives in the child rather
|
|
19
|
+
* than on the parent's hot path.
|
|
20
|
+
*
|
|
21
|
+
* `databaseTarget` is an optional parent-side override forwarded to
|
|
22
|
+
* the child. Set by `fireTelemetryAfterInitConsent` (where the
|
|
23
|
+
* config file does not yet exist on disk); left unset by the
|
|
24
|
+
* preAction-hook path so the child's c12 load supplies the value.
|
|
15
25
|
*/
|
|
16
26
|
export interface RunTelemetryInputs {
|
|
17
27
|
/** Sanitised commander snapshot — see `CommanderResultShape`. */
|
|
18
28
|
readonly command: CommanderResultShape;
|
|
19
29
|
/** This CLI's own version (from its `package.json`). */
|
|
20
30
|
readonly version: string;
|
|
21
|
-
/** Resolved `config.target.targetId`, or `null` when the config could not be loaded. */
|
|
22
|
-
readonly databaseTarget: string | null;
|
|
23
|
-
/** Declared extension-pack IDs, in any deterministic order. */
|
|
24
|
-
readonly extensions: readonly string[];
|
|
25
31
|
/** Absolute path of the project root (typically `process.cwd()`). */
|
|
26
32
|
readonly projectRoot: string;
|
|
33
|
+
/**
|
|
34
|
+
* Optional parent-side override for the c12-derived database target,
|
|
35
|
+
* forwarded verbatim to the child sender. Wins over the child's
|
|
36
|
+
* c12-derived value when present; `undefined` means "no override".
|
|
37
|
+
*/
|
|
38
|
+
readonly databaseTarget?: string;
|
|
27
39
|
/**
|
|
28
40
|
* Path to the sender entry compiled into this package's `dist/`.
|
|
29
41
|
* Resolved by the caller because the compiled sender lives at
|
|
@@ -85,10 +97,9 @@ export function runTelemetry(inputs: RunTelemetryInputs): TelemetryRunOutcome {
|
|
|
85
97
|
version: inputs.version,
|
|
86
98
|
command: sanitised.command,
|
|
87
99
|
flags: sanitised.flags,
|
|
88
|
-
databaseTarget: inputs.databaseTarget,
|
|
89
|
-
extensions: inputs.extensions,
|
|
90
100
|
projectRoot: inputs.projectRoot,
|
|
91
101
|
endpoint: resolveTelemetryEndpoint(env),
|
|
102
|
+
...ifDefined('databaseTarget', inputs.databaseTarget),
|
|
92
103
|
};
|
|
93
104
|
|
|
94
105
|
try {
|