@driftdev/cli 1.13.0 → 1.14.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 +1 -1
- package/dist/drift.js +30 -12
- package/package.json +2 -2
- package/schemas/drift.config.schema.json +11 -0
package/README.md
CHANGED
|
@@ -158,7 +158,7 @@ Validate @example blocks.
|
|
|
158
158
|
```bash
|
|
159
159
|
drift examples # presence check
|
|
160
160
|
drift examples --typecheck # type-check examples
|
|
161
|
-
drift examples --run # execute examples
|
|
161
|
+
drift examples --run # execute examples with // => assertions
|
|
162
162
|
drift examples --min 50 # fail if example coverage below 50%
|
|
163
163
|
```
|
|
164
164
|
|
package/dist/drift.js
CHANGED
|
@@ -737,6 +737,16 @@ function validateConfig(raw) {
|
|
|
737
737
|
}
|
|
738
738
|
}
|
|
739
739
|
}
|
|
740
|
+
if (obj.examples !== undefined) {
|
|
741
|
+
if (typeof obj.examples !== "object" || obj.examples === null) {
|
|
742
|
+
errors.push('"examples" must be an object');
|
|
743
|
+
} else {
|
|
744
|
+
const examples = obj.examples;
|
|
745
|
+
if (examples.run !== undefined && typeof examples.run !== "boolean") {
|
|
746
|
+
errors.push('"examples.run" must be a boolean');
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
740
750
|
if (errors.length > 0)
|
|
741
751
|
return { ok: false, errors };
|
|
742
752
|
const { $schema: _schema, ...rest } = obj;
|
|
@@ -3053,14 +3063,15 @@ function renderExamples(data) {
|
|
|
3053
3063
|
lines.push("");
|
|
3054
3064
|
}
|
|
3055
3065
|
if (data.run) {
|
|
3056
|
-
const { passed, failed, drifts, installSuccess, installError } = data.run;
|
|
3066
|
+
const { passed, failed, skipped, drifts, installSuccess, installError } = data.run;
|
|
3057
3067
|
if (!installSuccess) {
|
|
3058
|
-
lines.push(indent(`${c.gray("RUNTIME")} ${c.red("
|
|
3068
|
+
lines.push(indent(`${c.gray("RUNTIME")} ${c.red("failed")}`));
|
|
3059
3069
|
if (installError) {
|
|
3060
3070
|
lines.push(indent(` ${c.red(installError)}`));
|
|
3061
3071
|
}
|
|
3062
3072
|
} else {
|
|
3063
|
-
const
|
|
3073
|
+
const skipBit = skipped > 0 ? ` ${c.gray(`${skipped} skipped`)}` : "";
|
|
3074
|
+
const status = failed === 0 ? `${c.green(`${passed} passed`)}${skipBit}` : `${c.green(`${passed} passed`)} ${c.red(`${failed} failed`)}${skipBit}`;
|
|
3064
3075
|
lines.push(indent(`${c.gray("RUNTIME")} ${status}`));
|
|
3065
3076
|
if (drifts.length > 0) {
|
|
3066
3077
|
const shown = drifts.slice(0, 10);
|
|
@@ -3079,7 +3090,7 @@ function renderExamples(data) {
|
|
|
3079
3090
|
if (!ran.includes("typecheck") && !ran.includes("run")) {
|
|
3080
3091
|
lines.push(indent(c.gray("Tip: drift examples --typecheck to compile-check examples")));
|
|
3081
3092
|
} else if (!ran.includes("run")) {
|
|
3082
|
-
lines.push(indent(c.gray("Tip: drift examples --run to execute examples
|
|
3093
|
+
lines.push(indent(c.gray("Tip: drift examples --run to execute examples with // => assertions")));
|
|
3083
3094
|
}
|
|
3084
3095
|
lines.push("");
|
|
3085
3096
|
return lines.join(`
|
|
@@ -3100,7 +3111,7 @@ function findPackagePath(entryFile) {
|
|
|
3100
3111
|
return path22.dirname(entryFile);
|
|
3101
3112
|
}
|
|
3102
3113
|
function registerExamplesCommand(program) {
|
|
3103
|
-
program.command("examples [entry]").description("Validate @example blocks on exports").option("--typecheck", "Type-check examples with TypeScript").option("--run", "Execute examples
|
|
3114
|
+
program.command("examples [entry]").description("Validate @example blocks on exports").option("--typecheck", "Type-check examples with TypeScript").option("--run", "Execute examples that contain // => assertions (implies --typecheck; installs the package)").option("--yes", "Confirm execution (required when not a TTY)").option("--untrusted", "Treat the target as a third-party package (OS isolation; macOS only)").option("--all", "Run across all workspace packages").option("--private", "Include private packages in --all mode").option("--min <n>", "Minimum presence threshold (exit 1 if below)").action(async (entry, options) => {
|
|
3104
3115
|
const startTime = Date.now();
|
|
3105
3116
|
const version = getVersion();
|
|
3106
3117
|
try {
|
|
@@ -3109,9 +3120,13 @@ function registerExamplesCommand(program) {
|
|
|
3109
3120
|
validations.push("typecheck");
|
|
3110
3121
|
if (options.run)
|
|
3111
3122
|
validations.push("run");
|
|
3123
|
+
const { config } = loadConfig();
|
|
3112
3124
|
if (options.run) {
|
|
3113
|
-
|
|
3114
|
-
|
|
3125
|
+
const confirmed = Boolean(options.yes) || config.examples?.run === true || Boolean(process.stdin.isTTY);
|
|
3126
|
+
if (!confirmed) {
|
|
3127
|
+
formatError("examples", "--run requires --yes or examples.run: true in config when not running interactively", startTime, version);
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
3115
3130
|
}
|
|
3116
3131
|
if (options.all) {
|
|
3117
3132
|
const allPackages = discoverPackages(process.cwd());
|
|
@@ -3137,7 +3152,8 @@ function registerExamplesCommand(program) {
|
|
|
3137
3152
|
const result2 = await validateExamples(exps, {
|
|
3138
3153
|
validations,
|
|
3139
3154
|
packagePath: packagePath2,
|
|
3140
|
-
exportNames: exportNames2
|
|
3155
|
+
exportNames: exportNames2,
|
|
3156
|
+
untrusted: options.untrusted
|
|
3141
3157
|
});
|
|
3142
3158
|
const withEx = result2.presence?.withExamples ?? 0;
|
|
3143
3159
|
const total = result2.presence?.total ?? exps.length;
|
|
@@ -3147,8 +3163,9 @@ function registerExamplesCommand(program) {
|
|
|
3147
3163
|
totalAll += total;
|
|
3148
3164
|
if (result2.typecheck && result2.typecheck.failed > 0)
|
|
3149
3165
|
hasFailures = true;
|
|
3150
|
-
if (result2.run && result2.run.failed > 0)
|
|
3166
|
+
if (result2.run && (result2.run.failed > 0 || !result2.run.installSuccess)) {
|
|
3151
3167
|
hasFailures = true;
|
|
3168
|
+
}
|
|
3152
3169
|
}
|
|
3153
3170
|
const aggScore = totalAll > 0 ? Math.round(totalWith / totalAll * 100) : 100;
|
|
3154
3171
|
const data = {
|
|
@@ -3164,7 +3181,6 @@ function registerExamplesCommand(program) {
|
|
|
3164
3181
|
process.exitCode = 1;
|
|
3165
3182
|
return;
|
|
3166
3183
|
}
|
|
3167
|
-
const { config } = loadConfig();
|
|
3168
3184
|
const entryFile = entry ? path22.resolve(process.cwd(), entry) : config.entry ? path22.resolve(process.cwd(), config.entry) : detectEntry();
|
|
3169
3185
|
const { spec } = await cachedExtract(entryFile);
|
|
3170
3186
|
const exports = spec.exports ?? [];
|
|
@@ -3173,7 +3189,8 @@ function registerExamplesCommand(program) {
|
|
|
3173
3189
|
const result = await validateExamples(exports, {
|
|
3174
3190
|
validations,
|
|
3175
3191
|
packagePath,
|
|
3176
|
-
exportNames
|
|
3192
|
+
exportNames,
|
|
3193
|
+
untrusted: options.untrusted
|
|
3177
3194
|
});
|
|
3178
3195
|
const missingCount = result.presence?.missing?.length ?? 0;
|
|
3179
3196
|
const failedCount = (result.typecheck?.failed ?? 0) + (result.run?.failed ?? 0);
|
|
@@ -3191,8 +3208,9 @@ function registerExamplesCommand(program) {
|
|
|
3191
3208
|
}
|
|
3192
3209
|
if (result.typecheck && result.typecheck.failed > 0)
|
|
3193
3210
|
process.exitCode = 1;
|
|
3194
|
-
if (result.run && result.run.failed > 0)
|
|
3211
|
+
if (result.run && (result.run.failed > 0 || !result.run.installSuccess)) {
|
|
3195
3212
|
process.exitCode = 1;
|
|
3213
|
+
}
|
|
3196
3214
|
} catch (err) {
|
|
3197
3215
|
formatError("examples", err instanceof Error ? err.message : String(err), startTime, version);
|
|
3198
3216
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@driftdev/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0",
|
|
4
4
|
"description": "Drift CLI - detect when your docs drift from your code",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@driftdev/clarity-adapter": "^1.0.1",
|
|
49
49
|
"@driftdev/openapi-adapter": "^1.0.1",
|
|
50
|
-
"@driftdev/sdk": "^1.
|
|
50
|
+
"@driftdev/sdk": "^1.14.0",
|
|
51
51
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
52
52
|
"@openpkg-ts/sdk": "^0.51.0",
|
|
53
53
|
"@openpkg-ts/spec": "^0.50.0",
|
|
@@ -79,6 +79,17 @@
|
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
81
|
"additionalProperties": false
|
|
82
|
+
},
|
|
83
|
+
"examples": {
|
|
84
|
+
"type": "object",
|
|
85
|
+
"description": "Example execution policy",
|
|
86
|
+
"properties": {
|
|
87
|
+
"run": {
|
|
88
|
+
"type": "boolean",
|
|
89
|
+
"description": "Allow --run in non-TTY (CI) without --yes"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"additionalProperties": false
|
|
82
93
|
}
|
|
83
94
|
},
|
|
84
95
|
"additionalProperties": true
|