@donotdev/cli 0.0.14 → 0.0.15
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/dependencies-matrix.json +356 -88
- package/dist/bin/commands/agent-setup.js +7 -1
- package/dist/bin/commands/build.js +118 -38
- package/dist/bin/commands/bump.js +74 -28
- package/dist/bin/commands/cacheout.js +37 -9
- package/dist/bin/commands/create-app.js +222 -115
- package/dist/bin/commands/create-project.js +455 -140
- package/dist/bin/commands/deploy.js +1736 -697
- package/dist/bin/commands/dev.js +138 -23
- package/dist/bin/commands/emu.js +215 -58
- package/dist/bin/commands/format.js +37 -9
- package/dist/bin/commands/lint.js +37 -9
- package/dist/bin/commands/preview.js +142 -23
- package/dist/bin/commands/supabase-setup.d.ts +6 -0
- package/dist/bin/commands/supabase-setup.d.ts.map +1 -0
- package/dist/bin/commands/supabase-setup.js +7 -0
- package/dist/bin/commands/supabase-setup.js.map +1 -0
- package/dist/bin/commands/sync-secrets.js +211 -34
- package/dist/bin/commands/type-check.d.ts +14 -0
- package/dist/bin/commands/type-check.d.ts.map +1 -0
- package/dist/bin/commands/type-check.js +314 -0
- package/dist/bin/commands/type-check.js.map +1 -0
- package/dist/bin/commands/wai.js +3 -1
- package/dist/bin/dndev.js +27 -2
- package/dist/bin/donotdev.js +27 -2
- package/dist/index.js +3960 -3015
- package/package.json +2 -2
- package/templates/app-demo/src/App.tsx.example +1 -0
- package/templates/app-demo/src/pages/FullPage.tsx.example +2 -2
- package/templates/app-demo/src/pages/components/DemoLayout.tsx.example +2 -2
- package/templates/app-demo/src/themes.css.example +5 -12
- package/templates/app-expo/.env.example +64 -0
- package/templates/app-expo/.expo/README.md.example +5 -0
- package/templates/app-expo/.gitignore.example +36 -0
- package/templates/app-expo/README.md.example +58 -0
- package/templates/app-expo/app/.gitkeep +2 -0
- package/templates/app-expo/app/_layout.tsx.example +41 -0
- package/templates/app-expo/app/form.tsx.example +52 -0
- package/templates/app-expo/app/index.tsx.example +89 -0
- package/templates/app-expo/app/list.tsx.example +32 -0
- package/templates/app-expo/app/profile.tsx.example +76 -0
- package/templates/app-expo/app/signin.tsx.example +53 -0
- package/templates/app-expo/app.json.example +39 -0
- package/templates/app-expo/babel.config.js.example +10 -0
- package/templates/app-expo/eas.json.example +20 -0
- package/templates/app-expo/expo-env.d.ts.example +4 -0
- package/templates/app-expo/metro.config.js.example +20 -0
- package/templates/app-expo/service-account-key.json.example +12 -0
- package/templates/app-expo/tsconfig.json.example +19 -0
- package/templates/app-next/.env.example +4 -33
- package/templates/app-next/src/app/ClientLayout.tsx.example +2 -0
- package/templates/app-next/src/app/layout.tsx.example +7 -6
- package/templates/app-next/src/globals.css.example +2 -11
- package/templates/app-next/src/pages/HomePage.tsx.example +1 -1
- package/templates/app-next/src/themes.css.example +10 -13
- package/templates/app-vite/.env.example +3 -32
- package/templates/app-vite/index.html.example +2 -24
- package/templates/app-vite/src/App.tsx.example +2 -0
- package/templates/app-vite/src/globals.css.example +2 -12
- package/templates/app-vite/src/pages/FormPageExample.tsx.example +1 -2
- package/templates/app-vite/src/pages/HomePage.tsx.example +1 -1
- package/templates/app-vite/src/themes.css.example +109 -79
- package/templates/app-vite/vercel.json.example +11 -0
- package/templates/functions-firebase/build.mjs.example +2 -72
- package/templates/functions-firebase/functions-firebase/.env.example.example +23 -25
- package/templates/functions-firebase/functions-firebase/build.mjs.example +2 -72
- package/templates/functions-firebase/functions-firebase/tsconfig.json.example +1 -1
- package/templates/functions-supabase/supabase/functions/cancel-subscription/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/change-plan/index.ts.example +11 -0
- package/templates/functions-supabase/supabase/functions/create-checkout-session/index.ts.example +11 -0
- package/templates/functions-supabase/supabase/functions/create-customer-portal/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/crud/index.ts.example +16 -0
- package/templates/functions-supabase/supabase/functions/delete-account/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/get-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/get-user-auth-status/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/refresh-subscription-status/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/remove-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/functions/set-custom-claims/index.ts.example +7 -0
- package/templates/functions-supabase/supabase/migrations/20250101000000_idempotency.sql +24 -0
- package/templates/functions-supabase/supabase/migrations/20250101000001_rate_limits.sql +22 -0
- package/templates/functions-supabase/supabase/migrations/20250101000002_cleanup_jobs.sql +28 -0
- package/templates/functions-supabase/supabase/migrations/20250101000003_operation_metrics.sql +28 -0
- package/templates/functions-vercel/functions-vercel/tsconfig.json.example +1 -1
- package/templates/functions-vercel/functions-vercel/vercel.json.example +1 -1
- package/templates/functions-vercel/vercel.json.example +1 -1
- package/templates/github/github/workflows/firebase-deploy.yml.example +1 -1
- package/templates/github/workflows/firebase-deploy.yml.example +1 -1
- package/templates/overlay-firebase/env.fragment.example +34 -0
- package/templates/overlay-firebase/env.fragment.expo.example +34 -0
- package/templates/overlay-firebase/env.fragment.nextjs.example +34 -0
- package/templates/overlay-firebase/src/config/providers.expo.ts.example +49 -0
- package/templates/overlay-firebase/src/config/providers.ts.example +23 -0
- package/templates/overlay-supabase/env.fragment.example +7 -0
- package/templates/overlay-supabase/env.fragment.expo.example +7 -0
- package/templates/overlay-supabase/env.fragment.nextjs.example +7 -0
- package/templates/overlay-supabase/src/config/providers.expo.ts.example +35 -0
- package/templates/overlay-supabase/src/config/providers.ts.example +33 -0
- package/templates/overlay-supabase/vercel.headers.example +23 -0
- package/templates/overlay-supabase/vercel.json.example +22 -0
- package/templates/overlay-vercel/env.fragment.example +34 -0
- package/templates/overlay-vercel/env.fragment.nextjs.example +34 -0
- package/templates/overlay-vercel/src/config/providers.ts.example +24 -0
- package/templates/root-consumer/.claude/agents/architect.md.example +2 -310
- package/templates/root-consumer/.claude/agents/builder.md.example +2 -326
- package/templates/root-consumer/.claude/agents/coder.md.example +2 -83
- package/templates/root-consumer/.claude/agents/extractor.md.example +2 -231
- package/templates/root-consumer/.claude/agents/polisher.md.example +2 -132
- package/templates/root-consumer/.claude/agents/prompt-engineer.md.example +2 -81
- package/templates/root-consumer/.claude/commands/grill.md.example +30 -0
- package/templates/root-consumer/.claude/commands/techdebt.md.example +28 -0
- package/templates/root-consumer/.clinerules.example +1 -0
- package/templates/root-consumer/.cursor/rules/no-docs.mdc.example +15 -0
- package/templates/root-consumer/.cursorrules.example +1 -0
- package/templates/root-consumer/.github/copilot-instructions.md.example +1 -0
- package/templates/root-consumer/.windsurfrules.example +1 -0
- package/templates/root-consumer/AI.md.example +29 -123
- package/templates/root-consumer/CLAUDE.md.example +1 -134
- package/templates/root-consumer/CONVENTIONS.md.example +1 -0
- package/templates/root-consumer/GEMINI.md.example +1 -0
- package/templates/root-consumer/firebase.json.example +1 -1
- package/templates/root-consumer/guides/dndev/AGENT_START_HERE.md.example +20 -0
- package/templates/root-consumer/guides/dndev/COMPONENTS_ADV.md.example +0 -18
- package/templates/root-consumer/guides/dndev/COMPONENTS_UI.md.example +1 -1
- package/templates/root-consumer/guides/dndev/ENV_SETUP.md.example +99 -30
- package/templates/root-consumer/guides/dndev/INDEX.md.example +3 -1
- package/templates/root-consumer/guides/dndev/SETUP_CRUD.md.example +143 -12
- package/templates/root-consumer/guides/dndev/SETUP_FIREBASE.md.example +9 -3
- package/templates/root-consumer/guides/dndev/SETUP_SOC2.md.example +234 -0
- package/templates/root-consumer/guides/dndev/SETUP_SUPABASE.md.example +124 -0
- package/templates/root-consumer/guides/dndev/SETUP_THEMES.md.example +6 -2
- package/templates/root-consumer/guides/dndev/SETUP_VERCEL.md.example +176 -0
- package/templates/root-consumer/guides/dndev/USE_ROUTING.md.example +5 -9
- package/templates/root-consumer/guides/dndev/essences_reference.css.example +174 -0
- package/templates/root-consumer/guides/wai-way/agents/builder.md.example +10 -0
- package/templates/root-consumer/guides/wai-way/agents/extractor.md.example +25 -5
- package/templates/root-consumer/guides/wai-way/agents/polisher.md.example +13 -2
- package/templates/root-consumer/guides/wai-way/blueprints/0_brainstorm.md.example +2 -2
- package/templates/root-consumer/guides/wai-way/blueprints/1_scaffold.md.example +47 -11
- package/templates/root-consumer/guides/wai-way/blueprints/3_compose.md.example +15 -4
- package/templates/root-consumer/guides/wai-way/spec_template.md.example +7 -6
- package/templates/app-payload/.env.example +0 -28
- package/templates/app-payload/README.md.example +0 -233
- package/templates/app-payload/collections/Company.ts.example +0 -125
- package/templates/app-payload/collections/Hero.ts.example +0 -62
- package/templates/app-payload/collections/Media.ts.example +0 -41
- package/templates/app-payload/collections/Products.ts.example +0 -115
- package/templates/app-payload/collections/Services.ts.example +0 -104
- package/templates/app-payload/collections/Testimonials.ts.example +0 -92
- package/templates/app-payload/collections/Users.ts.example +0 -35
- package/templates/app-payload/src/server.ts.example +0 -79
- package/templates/app-payload/tsconfig.json.example +0 -24
|
@@ -7534,11 +7534,39 @@ var init_PathResolver = __esm({
|
|
|
7534
7534
|
});
|
|
7535
7535
|
|
|
7536
7536
|
// packages/tooling/src/utils/errors.ts
|
|
7537
|
-
var DoNotDevError;
|
|
7537
|
+
var DO_NOT_DEV_ERROR_CODES, DoNotDevError;
|
|
7538
7538
|
var init_errors = __esm({
|
|
7539
7539
|
"packages/tooling/src/utils/errors.ts"() {
|
|
7540
7540
|
"use strict";
|
|
7541
7541
|
init_utils();
|
|
7542
|
+
DO_NOT_DEV_ERROR_CODES = {
|
|
7543
|
+
CONFIGURATION_ERROR: "configuration-error",
|
|
7544
|
+
CONFIG_NOT_FOUND: "config-not-found",
|
|
7545
|
+
CONFIG_INVALID: "config-invalid",
|
|
7546
|
+
PATH_RESOLUTION_ERROR: "path-resolution-error",
|
|
7547
|
+
FILE_OPERATION_ERROR: "file-operation-error",
|
|
7548
|
+
FILE_NOT_FOUND: "file-not-found",
|
|
7549
|
+
PERMISSION_DENIED: "permission-denied",
|
|
7550
|
+
GENERATION_ERROR: "generation-error",
|
|
7551
|
+
TEMPLATE_ERROR: "template-error",
|
|
7552
|
+
TEMPLATE_NOT_FOUND: "template-not-found",
|
|
7553
|
+
CLI_EXECUTION_ERROR: "cli-execution-error",
|
|
7554
|
+
COMMAND_NOT_FOUND: "command-not-found",
|
|
7555
|
+
COMMAND_FAILED: "command-failed",
|
|
7556
|
+
VALIDATION_ERROR: "validation-error",
|
|
7557
|
+
SCHEMA_ERROR: "schema-error",
|
|
7558
|
+
DEPENDENCY_ERROR: "dependency-error",
|
|
7559
|
+
DEPENDENCY_NOT_FOUND: "dependency-not-found",
|
|
7560
|
+
DEPENDENCY_VERSION_ERROR: "dependency-version-error",
|
|
7561
|
+
INVALID_ARGUMENT: "invalid-argument",
|
|
7562
|
+
MISSING_ARGUMENT: "missing-argument",
|
|
7563
|
+
MISSING_PROJECT_ID: "missing-project-id",
|
|
7564
|
+
FIREBASE_CLI_ERROR: "firebase-cli-error",
|
|
7565
|
+
DEPLOYMENT_FAILED: "deployment-failed",
|
|
7566
|
+
OPERATION_CANCELLED: "operation-cancelled",
|
|
7567
|
+
TIMEOUT_ERROR: "timeout-error",
|
|
7568
|
+
UNKNOWN_ERROR: "unknown-error"
|
|
7569
|
+
};
|
|
7542
7570
|
DoNotDevError = class _DoNotDevError extends Error {
|
|
7543
7571
|
/** The error code categorizing this error */
|
|
7544
7572
|
code;
|
|
@@ -7558,7 +7586,7 @@ var init_errors = __esm({
|
|
|
7558
7586
|
* @param {Record<string, any>} [options.context] - Additional context data
|
|
7559
7587
|
* @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
|
|
7560
7588
|
*/
|
|
7561
|
-
constructor(message, code =
|
|
7589
|
+
constructor(message, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
|
|
7562
7590
|
super(message);
|
|
7563
7591
|
this.name = "DoNotDevError";
|
|
7564
7592
|
this.code = code;
|
|
@@ -7589,7 +7617,7 @@ var init_errors = __esm({
|
|
|
7589
7617
|
* @param {boolean} [options.displayable=true] - Whether this error should be displayed to the user
|
|
7590
7618
|
* @returns {DoNotDevError} New DoNotDev error wrapping the original
|
|
7591
7619
|
*/
|
|
7592
|
-
static from(error2, context, code =
|
|
7620
|
+
static from(error2, context, code = DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR, options) {
|
|
7593
7621
|
if (!(error2 instanceof Error)) {
|
|
7594
7622
|
return new _DoNotDevError(
|
|
7595
7623
|
`Unknown error: ${String(error2)}`,
|
|
@@ -7626,21 +7654,21 @@ var init_errors = __esm({
|
|
|
7626
7654
|
}
|
|
7627
7655
|
const message = error2.message.toLowerCase();
|
|
7628
7656
|
if (error2.name === "ValidationError" || message.includes("validation")) {
|
|
7629
|
-
return
|
|
7657
|
+
return DO_NOT_DEV_ERROR_CODES.VALIDATION_ERROR;
|
|
7630
7658
|
}
|
|
7631
7659
|
if (message.includes("not found") || message.includes("no such file")) {
|
|
7632
|
-
return
|
|
7660
|
+
return DO_NOT_DEV_ERROR_CODES.FILE_NOT_FOUND;
|
|
7633
7661
|
}
|
|
7634
7662
|
if (message.includes("permission") || message.includes("access denied")) {
|
|
7635
|
-
return
|
|
7663
|
+
return DO_NOT_DEV_ERROR_CODES.PERMISSION_DENIED;
|
|
7636
7664
|
}
|
|
7637
7665
|
if (message.includes("timeout") || message.includes("timed out")) {
|
|
7638
|
-
return
|
|
7666
|
+
return DO_NOT_DEV_ERROR_CODES.TIMEOUT_ERROR;
|
|
7639
7667
|
}
|
|
7640
7668
|
if (message.includes("dependency") || message.includes("module not found")) {
|
|
7641
|
-
return
|
|
7669
|
+
return DO_NOT_DEV_ERROR_CODES.DEPENDENCY_ERROR;
|
|
7642
7670
|
}
|
|
7643
|
-
return
|
|
7671
|
+
return DO_NOT_DEV_ERROR_CODES.UNKNOWN_ERROR;
|
|
7644
7672
|
}
|
|
7645
7673
|
};
|
|
7646
7674
|
}
|
|
@@ -7717,18 +7745,7 @@ var init_utils = __esm({
|
|
|
7717
7745
|
}
|
|
7718
7746
|
});
|
|
7719
7747
|
|
|
7720
|
-
// packages/cli/src/bin/commands/sync-secrets.ts
|
|
7721
|
-
init_utils();
|
|
7722
|
-
|
|
7723
|
-
// packages/tooling/src/index.ts
|
|
7724
|
-
init_utils();
|
|
7725
|
-
|
|
7726
|
-
// packages/tooling/src/cli/index.ts
|
|
7727
|
-
init_utils();
|
|
7728
|
-
|
|
7729
7748
|
// packages/tooling/src/utils/cli-input.ts
|
|
7730
|
-
init_utils();
|
|
7731
|
-
init_dist2();
|
|
7732
7749
|
async function askForSelection(message, choices, defaultValue = 0) {
|
|
7733
7750
|
const options = choices.map((choice) => ({
|
|
7734
7751
|
value: choice.value,
|
|
@@ -7746,13 +7763,16 @@ async function askForSelection(message, choices, defaultValue = 0) {
|
|
|
7746
7763
|
}
|
|
7747
7764
|
return result;
|
|
7748
7765
|
}
|
|
7766
|
+
var init_cli_input = __esm({
|
|
7767
|
+
"packages/tooling/src/utils/cli-input.ts"() {
|
|
7768
|
+
"use strict";
|
|
7769
|
+
init_utils();
|
|
7770
|
+
init_dist2();
|
|
7771
|
+
}
|
|
7772
|
+
});
|
|
7749
7773
|
|
|
7750
7774
|
// packages/tooling/src/apps/sync-secrets.ts
|
|
7751
|
-
init_utils();
|
|
7752
7775
|
import { spawnSync } from "node:child_process";
|
|
7753
|
-
init_cli_output();
|
|
7754
|
-
init_errors();
|
|
7755
|
-
init_pathResolver();
|
|
7756
7776
|
function parseEnvFile(filePath) {
|
|
7757
7777
|
if (!pathExists(filePath)) {
|
|
7758
7778
|
throw new DoNotDevError(
|
|
@@ -7761,7 +7781,8 @@ function parseEnvFile(filePath) {
|
|
|
7761
7781
|
{ context: { filePath } }
|
|
7762
7782
|
);
|
|
7763
7783
|
}
|
|
7764
|
-
const
|
|
7784
|
+
const contentRaw = readSync(filePath, { format: "text" });
|
|
7785
|
+
const content = typeof contentRaw === "string" ? contentRaw : null;
|
|
7765
7786
|
if (!content) {
|
|
7766
7787
|
throw new Error(`Failed to read secrets file: ${filePath}`);
|
|
7767
7788
|
}
|
|
@@ -7836,7 +7857,8 @@ function detectFirebaseProjectId(cwd) {
|
|
|
7836
7857
|
const firebasercPath = joinPath(searchDir, ".firebaserc");
|
|
7837
7858
|
if (pathExists(firebasercPath)) {
|
|
7838
7859
|
try {
|
|
7839
|
-
const
|
|
7860
|
+
const firebasercRaw = readSync(firebasercPath, { format: "json" });
|
|
7861
|
+
const firebaserc = firebasercRaw && typeof firebasercRaw === "object" ? firebasercRaw : null;
|
|
7840
7862
|
if (firebaserc && firebaserc.projects?.default) {
|
|
7841
7863
|
return firebaserc.projects.default;
|
|
7842
7864
|
}
|
|
@@ -7849,7 +7871,8 @@ function detectFirebaseProjectId(cwd) {
|
|
|
7849
7871
|
const firebasercPath2 = joinPath(current, ".firebaserc");
|
|
7850
7872
|
if (pathExists(firebasercPath2)) {
|
|
7851
7873
|
try {
|
|
7852
|
-
const
|
|
7874
|
+
const firebasercRaw = readSync(firebasercPath2, { format: "json" });
|
|
7875
|
+
const firebaserc = firebasercRaw && typeof firebasercRaw === "object" ? firebasercRaw : null;
|
|
7853
7876
|
if (firebaserc && firebaserc.projects?.default) {
|
|
7854
7877
|
return firebaserc.projects.default;
|
|
7855
7878
|
}
|
|
@@ -8065,12 +8088,99 @@ function setVercelSecret(key, value, projectId, dryRun = false) {
|
|
|
8065
8088
|
);
|
|
8066
8089
|
}
|
|
8067
8090
|
}
|
|
8091
|
+
function detectGitHubRepo() {
|
|
8092
|
+
try {
|
|
8093
|
+
const result = spawnSync("git", ["remote", "get-url", "origin"], {
|
|
8094
|
+
encoding: "utf8",
|
|
8095
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
8096
|
+
});
|
|
8097
|
+
if (result.status !== 0 || !result.stdout) return void 0;
|
|
8098
|
+
const url = result.stdout.trim();
|
|
8099
|
+
const sshMatch = url.match(/github\.com[:/]([^/]+\/[^/.]+)/);
|
|
8100
|
+
if (sshMatch) return sshMatch[1];
|
|
8101
|
+
const httpsMatch = url.match(/github\.com\/([^/]+\/[^/.]+)/);
|
|
8102
|
+
if (httpsMatch) return httpsMatch[1];
|
|
8103
|
+
return void 0;
|
|
8104
|
+
} catch {
|
|
8105
|
+
return void 0;
|
|
8106
|
+
}
|
|
8107
|
+
}
|
|
8108
|
+
function setGitHubSecret(key, value, repo, dryRun = false) {
|
|
8109
|
+
if (dryRun) {
|
|
8110
|
+
log.info(
|
|
8111
|
+
`[DRY RUN] Would set GitHub secret: ${key}${repo ? ` (repo: ${repo})` : ""}`
|
|
8112
|
+
);
|
|
8113
|
+
return;
|
|
8114
|
+
}
|
|
8115
|
+
try {
|
|
8116
|
+
log.info(`Setting GitHub secret: ${key}${repo ? ` (repo: ${repo})` : ""}`);
|
|
8117
|
+
const args = ["secret", "set", key];
|
|
8118
|
+
if (repo) {
|
|
8119
|
+
args.push("--repo", repo);
|
|
8120
|
+
}
|
|
8121
|
+
const result = spawnSync("gh", args, {
|
|
8122
|
+
input: value,
|
|
8123
|
+
encoding: "utf8",
|
|
8124
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
8125
|
+
});
|
|
8126
|
+
if (result.error) {
|
|
8127
|
+
throw result.error;
|
|
8128
|
+
}
|
|
8129
|
+
if (result.status !== 0) {
|
|
8130
|
+
const stderr = result.stderr?.toString() || "";
|
|
8131
|
+
const stdout = result.stdout?.toString() || "";
|
|
8132
|
+
const errorOutput = stderr || stdout;
|
|
8133
|
+
if (errorOutput.includes("not logged in") || errorOutput.includes("authentication")) {
|
|
8134
|
+
throw new DoNotDevError(
|
|
8135
|
+
`GitHub CLI authentication required. Run 'gh auth login' to authenticate.`,
|
|
8136
|
+
"permission-denied",
|
|
8137
|
+
{ context: { key, error: errorOutput } }
|
|
8138
|
+
);
|
|
8139
|
+
}
|
|
8140
|
+
throw new Error(
|
|
8141
|
+
`gh CLI exited with code ${result.status}
|
|
8142
|
+
${errorOutput}`
|
|
8143
|
+
);
|
|
8144
|
+
}
|
|
8145
|
+
log.success(`GitHub secret ${key} set successfully`);
|
|
8146
|
+
} catch (err) {
|
|
8147
|
+
if (err instanceof DoNotDevError) throw err;
|
|
8148
|
+
log.error(`Failed to set GitHub secret ${key}:`, err);
|
|
8149
|
+
throw new DoNotDevError(
|
|
8150
|
+
`Failed to set GitHub secret ${key}`,
|
|
8151
|
+
"command-failed",
|
|
8152
|
+
{
|
|
8153
|
+
context: {
|
|
8154
|
+
target: "github",
|
|
8155
|
+
key,
|
|
8156
|
+
error: err instanceof Error ? err.message : String(err)
|
|
8157
|
+
}
|
|
8158
|
+
}
|
|
8159
|
+
);
|
|
8160
|
+
}
|
|
8161
|
+
}
|
|
8162
|
+
function uploadServiceAccountToGitHub(appDir, repo, dryRun = false, staging = false) {
|
|
8163
|
+
const fileName = staging ? "service-account-key.staging.json" : "service-account-key.json";
|
|
8164
|
+
const secretName = staging ? "FIREBASE_SERVICE_ACCOUNT_STAGING" : "FIREBASE_SERVICE_ACCOUNT";
|
|
8165
|
+
const filePath = joinPath(appDir, fileName);
|
|
8166
|
+
if (!pathExists(filePath)) {
|
|
8167
|
+
log.debug(`No ${fileName} found in ${appDir}, skipping GitHub upload`);
|
|
8168
|
+
return;
|
|
8169
|
+
}
|
|
8170
|
+
const contentRaw = readSync(filePath, { format: "text" });
|
|
8171
|
+
const content = typeof contentRaw === "string" ? contentRaw : null;
|
|
8172
|
+
if (!content) return;
|
|
8173
|
+
const encoded = Buffer2.from(content).toString("base64");
|
|
8174
|
+
setGitHubSecret(secretName, encoded, repo, dryRun);
|
|
8175
|
+
}
|
|
8068
8176
|
async function main(options = {}) {
|
|
8069
8177
|
const config = {
|
|
8070
8178
|
envFile: options.envFile || ".env",
|
|
8071
8179
|
platform: options.platform,
|
|
8072
8180
|
projectId: options.projectId,
|
|
8073
8181
|
vercelProjectId: options.vercelProjectId,
|
|
8182
|
+
target: options.target || "runtime",
|
|
8183
|
+
repo: options.repo,
|
|
8074
8184
|
dryRun: options.dryRun ?? false,
|
|
8075
8185
|
verbose: options.verbose ?? false
|
|
8076
8186
|
};
|
|
@@ -8082,20 +8192,22 @@ Usage: bun run sync-secrets [options]
|
|
|
8082
8192
|
|
|
8083
8193
|
Options:
|
|
8084
8194
|
--env-file <path> Path to .env file (default: .env)
|
|
8085
|
-
--
|
|
8195
|
+
--target <target> Sync target: 'runtime' (default) or 'github'
|
|
8196
|
+
--platform <platform> Platform to sync to: 'firebase' or 'vercel' (runtime target only, auto-detected)
|
|
8086
8197
|
--project <id> Firebase project ID (for Firebase platform)
|
|
8087
8198
|
--vercel-project <id> Vercel project ID (for Vercel platform)
|
|
8199
|
+
--repo <owner/repo> GitHub repository (github target only, auto-detected from git remote)
|
|
8088
8200
|
--dry-run, --dry Show what would be done without actually setting secrets
|
|
8089
8201
|
--verbose Show detailed output
|
|
8090
8202
|
--help Show this help message
|
|
8091
8203
|
|
|
8092
8204
|
Examples:
|
|
8093
|
-
|
|
8094
|
-
|
|
8095
|
-
|
|
8096
|
-
|
|
8097
|
-
|
|
8098
|
-
|
|
8205
|
+
dndev sync-secrets # sync to Firebase/Vercel runtime
|
|
8206
|
+
dndev sync-secrets --target github # sync to GitHub Secrets
|
|
8207
|
+
dndev sync-secrets --target github --repo owner/repo # sync to specific repo
|
|
8208
|
+
dndev sync-secrets --platform=firebase
|
|
8209
|
+
dndev sync-secrets --dry-run
|
|
8210
|
+
dndev sync-secrets --env-file .env.production --project my-project
|
|
8099
8211
|
`);
|
|
8100
8212
|
return 0;
|
|
8101
8213
|
}
|
|
@@ -8135,6 +8247,51 @@ Examples:
|
|
|
8135
8247
|
}
|
|
8136
8248
|
}
|
|
8137
8249
|
const envFilePath = joinPath(currentDir, config.envFile);
|
|
8250
|
+
const syncTarget = config.target || "runtime";
|
|
8251
|
+
if (syncTarget === "github") {
|
|
8252
|
+
const repo = config.repo || detectGitHubRepo();
|
|
8253
|
+
if (!repo) {
|
|
8254
|
+
log.error(
|
|
8255
|
+
"Could not detect GitHub repository. Use --repo owner/repo or ensure a GitHub remote is configured."
|
|
8256
|
+
);
|
|
8257
|
+
return 1;
|
|
8258
|
+
}
|
|
8259
|
+
log.info(`Syncing secrets to GitHub repository: ${repo}`);
|
|
8260
|
+
const secrets2 = parseEnvFile(envFilePath);
|
|
8261
|
+
const secretKeys2 = Object.keys(secrets2);
|
|
8262
|
+
if (secretKeys2.length === 0) {
|
|
8263
|
+
log.info("No secrets found in .env file");
|
|
8264
|
+
} else {
|
|
8265
|
+
log.info(`Found ${secretKeys2.length} secrets to sync to GitHub:`);
|
|
8266
|
+
secretKeys2.forEach((key) => log.info(` ${key}`));
|
|
8267
|
+
for (const [key, value] of Object.entries(secrets2)) {
|
|
8268
|
+
setGitHubSecret(key, value, repo, config.dryRun);
|
|
8269
|
+
}
|
|
8270
|
+
}
|
|
8271
|
+
if (firebaseProjectDir) {
|
|
8272
|
+
uploadServiceAccountToGitHub(
|
|
8273
|
+
firebaseProjectDir,
|
|
8274
|
+
repo,
|
|
8275
|
+
config.dryRun,
|
|
8276
|
+
false
|
|
8277
|
+
);
|
|
8278
|
+
uploadServiceAccountToGitHub(
|
|
8279
|
+
firebaseProjectDir,
|
|
8280
|
+
repo,
|
|
8281
|
+
config.dryRun,
|
|
8282
|
+
true
|
|
8283
|
+
);
|
|
8284
|
+
} else {
|
|
8285
|
+
uploadServiceAccountToGitHub(currentDir, repo, config.dryRun, false);
|
|
8286
|
+
uploadServiceAccountToGitHub(currentDir, repo, config.dryRun, true);
|
|
8287
|
+
}
|
|
8288
|
+
if (config.dryRun) {
|
|
8289
|
+
log.success("\nDry run completed. No GitHub secrets were set.");
|
|
8290
|
+
} else {
|
|
8291
|
+
log.success("\nAll secrets synced to GitHub successfully!");
|
|
8292
|
+
}
|
|
8293
|
+
return 0;
|
|
8294
|
+
}
|
|
8138
8295
|
const platform = config.platform || detectPlatform();
|
|
8139
8296
|
log.info(`Reading secrets from: ${envFilePath}`);
|
|
8140
8297
|
if (config.verbose) {
|
|
@@ -8195,6 +8352,26 @@ All secrets synced successfully to ${platform}!`);
|
|
|
8195
8352
|
return 1;
|
|
8196
8353
|
}
|
|
8197
8354
|
}
|
|
8355
|
+
var init_sync_secrets = __esm({
|
|
8356
|
+
"packages/tooling/src/apps/sync-secrets.ts"() {
|
|
8357
|
+
"use strict";
|
|
8358
|
+
init_utils();
|
|
8359
|
+
init_cli_input();
|
|
8360
|
+
init_cli_output();
|
|
8361
|
+
init_errors();
|
|
8362
|
+
init_pathResolver();
|
|
8363
|
+
}
|
|
8364
|
+
});
|
|
8365
|
+
|
|
8366
|
+
// packages/cli/src/bin/commands/sync-secrets.ts
|
|
8367
|
+
init_utils();
|
|
8368
|
+
|
|
8369
|
+
// packages/tooling/src/index.ts
|
|
8370
|
+
init_utils();
|
|
8371
|
+
|
|
8372
|
+
// packages/tooling/src/cli/index.ts
|
|
8373
|
+
init_utils();
|
|
8374
|
+
init_sync_secrets();
|
|
8198
8375
|
export {
|
|
8199
8376
|
main
|
|
8200
8377
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface TypeCheckOptions {
|
|
2
|
+
/** Optional: scope to one app subdirectory */
|
|
3
|
+
app?: string;
|
|
4
|
+
verbose?: boolean;
|
|
5
|
+
quiet?: boolean;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Type-check all packages with a `type-check` script in the consumer project.
|
|
9
|
+
*
|
|
10
|
+
* @param options - Command options
|
|
11
|
+
* @returns Exit code: 0 = all pass, 1 = any failure
|
|
12
|
+
*/
|
|
13
|
+
export declare function main(options?: TypeCheckOptions): Promise<number>;
|
|
14
|
+
//# sourceMappingURL=type-check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-check.d.ts","sourceRoot":"","sources":["../../../src/bin/commands/type-check.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAoQD;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkF1E"}
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
// packages/cli/src/bin/commands/type-check.ts
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview dndev tc — TypeScript type-check for consumer projects
|
|
4
|
+
* Discovers packages with a `type-check` script and runs them.
|
|
5
|
+
* Agent-friendly: plain structured output when not a TTY.
|
|
6
|
+
*
|
|
7
|
+
* @version 0.0.1
|
|
8
|
+
* @since 0.0.1
|
|
9
|
+
* @author AMBROISE PARK Consulting
|
|
10
|
+
*/
|
|
11
|
+
import { spawn } from 'node:child_process';
|
|
12
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Package manager detection
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
/**
|
|
18
|
+
* Detect package manager from lockfile in a directory.
|
|
19
|
+
* Walks up to find the nearest lockfile.
|
|
20
|
+
*/
|
|
21
|
+
function detectPackageManager(dir) {
|
|
22
|
+
let current = dir;
|
|
23
|
+
for (let i = 0; i < 10; i++) {
|
|
24
|
+
if (existsSync(join(current, 'bun.lockb')))
|
|
25
|
+
return 'bun';
|
|
26
|
+
if (existsSync(join(current, 'yarn.lock')))
|
|
27
|
+
return 'yarn';
|
|
28
|
+
if (existsSync(join(current, 'pnpm-lock.yaml')))
|
|
29
|
+
return 'pnpm';
|
|
30
|
+
if (existsSync(join(current, 'package-lock.json')))
|
|
31
|
+
return 'npm';
|
|
32
|
+
const parent = join(current, '..');
|
|
33
|
+
if (parent === current)
|
|
34
|
+
break;
|
|
35
|
+
current = parent;
|
|
36
|
+
}
|
|
37
|
+
return 'bun'; // default
|
|
38
|
+
}
|
|
39
|
+
// ---------------------------------------------------------------------------
|
|
40
|
+
// Package discovery
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
const SKIP_DIRS = new Set([
|
|
43
|
+
'node_modules',
|
|
44
|
+
'dist',
|
|
45
|
+
'.next',
|
|
46
|
+
'.turbo',
|
|
47
|
+
'build',
|
|
48
|
+
'coverage',
|
|
49
|
+
'.git',
|
|
50
|
+
'.bun',
|
|
51
|
+
]);
|
|
52
|
+
/**
|
|
53
|
+
* Find all package.json files recursively from a root directory,
|
|
54
|
+
* skipping common non-source directories.
|
|
55
|
+
*/
|
|
56
|
+
function findPackageJsonFiles(rootDir) {
|
|
57
|
+
const results = [];
|
|
58
|
+
function walk(dir) {
|
|
59
|
+
let entries;
|
|
60
|
+
try {
|
|
61
|
+
entries = readdirSync(dir);
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
for (const entry of entries) {
|
|
67
|
+
if (SKIP_DIRS.has(entry))
|
|
68
|
+
continue;
|
|
69
|
+
const fullPath = join(dir, entry);
|
|
70
|
+
try {
|
|
71
|
+
const stat = statSync(fullPath);
|
|
72
|
+
if (stat.isDirectory()) {
|
|
73
|
+
walk(fullPath);
|
|
74
|
+
}
|
|
75
|
+
else if (entry === 'package.json') {
|
|
76
|
+
results.push(fullPath);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// skip inaccessible
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
walk(rootDir);
|
|
85
|
+
return results;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Discover packages with a `type-check` script in cwd.
|
|
89
|
+
* Optionally filtered to packages whose path or name includes `filter`.
|
|
90
|
+
*/
|
|
91
|
+
function discoverPackages(cwd, filter) {
|
|
92
|
+
const packageFiles = findPackageJsonFiles(cwd);
|
|
93
|
+
const packages = [];
|
|
94
|
+
for (const pkgFile of packageFiles) {
|
|
95
|
+
try {
|
|
96
|
+
// Read synchronously — we're in a CLI
|
|
97
|
+
const raw = readFileSync(pkgFile, 'utf-8');
|
|
98
|
+
const json = JSON.parse(raw);
|
|
99
|
+
const name = typeof json.name === 'string' ? json.name : undefined;
|
|
100
|
+
const scripts = (json.scripts ?? {});
|
|
101
|
+
if (!scripts['type-check'])
|
|
102
|
+
continue;
|
|
103
|
+
const pkgDir = join(pkgFile, '..');
|
|
104
|
+
// Compute relative path from cwd
|
|
105
|
+
const relativePath = pkgDir === cwd
|
|
106
|
+
? '.'
|
|
107
|
+
: pkgDir.startsWith(cwd + '/')
|
|
108
|
+
? pkgDir.slice(cwd.length + 1)
|
|
109
|
+
: pkgDir;
|
|
110
|
+
if (filter) {
|
|
111
|
+
const filterLower = filter.toLowerCase();
|
|
112
|
+
const nameLower = (name ?? '').toLowerCase();
|
|
113
|
+
const relLower = relativePath.toLowerCase();
|
|
114
|
+
if (!nameLower.includes(filterLower) && !relLower.includes(filterLower)) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
packages.push({
|
|
119
|
+
name: name ?? relativePath,
|
|
120
|
+
path: pkgDir,
|
|
121
|
+
relativePath,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return packages.sort((a, b) => a.name.localeCompare(b.name));
|
|
129
|
+
}
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// TypeScript error parsing
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
/**
|
|
134
|
+
* Parse TypeScript errors from tsc output.
|
|
135
|
+
* Returns lines matching `error TS####` format.
|
|
136
|
+
*/
|
|
137
|
+
function parseTypeScriptErrors(output) {
|
|
138
|
+
const lines = output.split('\n');
|
|
139
|
+
const errorLines = [];
|
|
140
|
+
const errorPattern = /error TS\d+/;
|
|
141
|
+
let errorCount = 0;
|
|
142
|
+
for (let i = 0; i < lines.length; i++) {
|
|
143
|
+
const line = lines[i];
|
|
144
|
+
if (!line)
|
|
145
|
+
continue;
|
|
146
|
+
if (errorPattern.test(line)) {
|
|
147
|
+
errorCount++;
|
|
148
|
+
errorLines.push(line.trim());
|
|
149
|
+
// Include indented continuation line if present
|
|
150
|
+
if (i + 1 < lines.length) {
|
|
151
|
+
const next = lines[i + 1];
|
|
152
|
+
if (next && /^\s+/.test(next)) {
|
|
153
|
+
errorLines.push(next.trimEnd());
|
|
154
|
+
i++;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return { errorCount, errorLines };
|
|
160
|
+
}
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
// Per-package type-check runner
|
|
163
|
+
// ---------------------------------------------------------------------------
|
|
164
|
+
/**
|
|
165
|
+
* Run `bun run type-check` (or appropriate package manager) in a package dir.
|
|
166
|
+
*/
|
|
167
|
+
function runTypeCheckInPackage(pkg, pm) {
|
|
168
|
+
return new Promise((resolve) => {
|
|
169
|
+
let stdout = '';
|
|
170
|
+
let stderr = '';
|
|
171
|
+
const [cmd, ...cmdArgs] = pm === 'bun'
|
|
172
|
+
? ['bun', 'run', 'type-check']
|
|
173
|
+
: pm === 'yarn'
|
|
174
|
+
? ['yarn', 'run', 'type-check']
|
|
175
|
+
: pm === 'pnpm'
|
|
176
|
+
? ['pnpm', 'run', 'type-check']
|
|
177
|
+
: ['npm', 'run', 'type-check'];
|
|
178
|
+
const child = spawn(cmd, cmdArgs, {
|
|
179
|
+
cwd: pkg.path,
|
|
180
|
+
stdio: 'pipe',
|
|
181
|
+
shell: true,
|
|
182
|
+
});
|
|
183
|
+
child.stdout?.on('data', (data) => {
|
|
184
|
+
stdout += data.toString('utf8');
|
|
185
|
+
});
|
|
186
|
+
child.stderr?.on('data', (data) => {
|
|
187
|
+
stderr += data.toString('utf8');
|
|
188
|
+
});
|
|
189
|
+
child.on('close', (code) => {
|
|
190
|
+
const allOutput = stdout + (stderr ? '\n' + stderr : '');
|
|
191
|
+
const { errorCount, errorLines } = parseTypeScriptErrors(allOutput);
|
|
192
|
+
resolve({
|
|
193
|
+
success: code === 0,
|
|
194
|
+
output: allOutput,
|
|
195
|
+
errors: errorLines,
|
|
196
|
+
errorCount,
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
child.on('error', (err) => {
|
|
200
|
+
const msg = `Failed to run type-check: ${err.message}`;
|
|
201
|
+
resolve({
|
|
202
|
+
success: false,
|
|
203
|
+
output: msg,
|
|
204
|
+
errors: [msg],
|
|
205
|
+
errorCount: 1,
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
// ---------------------------------------------------------------------------
|
|
211
|
+
// TTY spinner (clack) — only imported when running in TTY
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
async function runWithSpinner(pkg, pm) {
|
|
214
|
+
// Dynamic import to avoid side effects when not needed
|
|
215
|
+
const { spinner } = await import('@clack/prompts');
|
|
216
|
+
const s = spinner();
|
|
217
|
+
s.start(`Type-checking ${pkg.name} (${pkg.relativePath})...`);
|
|
218
|
+
const result = await runTypeCheckInPackage(pkg, pm);
|
|
219
|
+
if (result.success) {
|
|
220
|
+
s.stop(`${pkg.name} — No errors`);
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
s.stop(`${pkg.name} — ${result.errorCount} error(s)`);
|
|
224
|
+
}
|
|
225
|
+
return result;
|
|
226
|
+
}
|
|
227
|
+
// ---------------------------------------------------------------------------
|
|
228
|
+
// Main entry point
|
|
229
|
+
// ---------------------------------------------------------------------------
|
|
230
|
+
/**
|
|
231
|
+
* Type-check all packages with a `type-check` script in the consumer project.
|
|
232
|
+
*
|
|
233
|
+
* @param options - Command options
|
|
234
|
+
* @returns Exit code: 0 = all pass, 1 = any failure
|
|
235
|
+
*/
|
|
236
|
+
export async function main(options = {}) {
|
|
237
|
+
const cwd = process.cwd();
|
|
238
|
+
const isTTY = process.stdout.isTTY;
|
|
239
|
+
const packages = discoverPackages(cwd, options.app);
|
|
240
|
+
if (packages.length === 0) {
|
|
241
|
+
if (isTTY) {
|
|
242
|
+
console.log('No packages with a type-check script found.');
|
|
243
|
+
if (options.app) {
|
|
244
|
+
console.log(` Filter: ${options.app}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
console.log('RESULT: 0 passed, 0 failed, 0 total errors');
|
|
249
|
+
}
|
|
250
|
+
return 0;
|
|
251
|
+
}
|
|
252
|
+
const pm = detectPackageManager(cwd);
|
|
253
|
+
let passed = 0;
|
|
254
|
+
let failed = 0;
|
|
255
|
+
let totalErrors = 0;
|
|
256
|
+
if (isTTY) {
|
|
257
|
+
// TTY mode: spinner per package + summary
|
|
258
|
+
const { intro, outro } = await import('@clack/prompts');
|
|
259
|
+
intro('dndev tc — TypeScript type-check');
|
|
260
|
+
const failedPackages = [];
|
|
261
|
+
for (const pkg of packages) {
|
|
262
|
+
const result = await runWithSpinner(pkg, pm);
|
|
263
|
+
if (result.success) {
|
|
264
|
+
passed++;
|
|
265
|
+
}
|
|
266
|
+
else {
|
|
267
|
+
failed++;
|
|
268
|
+
totalErrors += result.errorCount;
|
|
269
|
+
failedPackages.push({ pkg, result });
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (failedPackages.length > 0 && options.verbose) {
|
|
273
|
+
const { log } = await import('@clack/prompts');
|
|
274
|
+
for (const { pkg, result } of failedPackages) {
|
|
275
|
+
log.error(`\n${pkg.name} (${pkg.relativePath}) — ${result.errorCount} error(s):`);
|
|
276
|
+
for (const line of result.errors) {
|
|
277
|
+
log.error(` ${line}`);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
else if (failedPackages.length > 0) {
|
|
282
|
+
const { log } = await import('@clack/prompts');
|
|
283
|
+
log.info('Run with --verbose to see detailed error messages');
|
|
284
|
+
}
|
|
285
|
+
if (failed === 0) {
|
|
286
|
+
outro(`All ${passed} package(s) passed type-check`);
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
outro(`${passed} passed, ${failed} failed, ${totalErrors} total error(s)`);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
// Non-TTY (agent) mode: structured plain text
|
|
294
|
+
for (const pkg of packages) {
|
|
295
|
+
console.log(`CHECKING ${pkg.name} (${pkg.relativePath})`);
|
|
296
|
+
const result = await runTypeCheckInPackage(pkg, pm);
|
|
297
|
+
if (result.success) {
|
|
298
|
+
console.log(`PASS ${pkg.name}`);
|
|
299
|
+
passed++;
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
console.log(`FAIL ${pkg.name}: ${result.errorCount} error(s)`);
|
|
303
|
+
for (const line of result.errors) {
|
|
304
|
+
console.log(` ${line}`);
|
|
305
|
+
}
|
|
306
|
+
failed++;
|
|
307
|
+
totalErrors += result.errorCount;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
console.log(`RESULT: ${passed} passed, ${failed} failed, ${totalErrors} total errors`);
|
|
311
|
+
}
|
|
312
|
+
return failed > 0 ? 1 : 0;
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=type-check.js.map
|