better-supabase 0.2.0 → 0.4.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 +37 -33
- package/dist/base64-D2gsioCY.js +42 -0
- package/dist/claims-BAf6c7is.js +48 -0
- package/dist/cli/_format-Cax5EsM9.js +101 -0
- package/dist/cli/bin.js +39 -6
- package/dist/cli/command-CK14fP91.js +502 -0
- package/dist/cli/compare-BmIWVEui.js +9 -0
- package/dist/cli/config-D9R0o1LH.js +1895 -0
- package/dist/cli/config-SSKSTUl2.js +2 -0
- package/dist/cli/db-DOBPt660.js +52 -0
- package/dist/cli/dist-B1MvLv-M.js +129 -0
- package/dist/cli/dist-CFgGknmZ.js +1112 -0
- package/dist/cli/dist-Du7VnEUG.js +621 -0
- package/dist/cli/doctor-BOym3mbL.js +2382 -0
- package/dist/cli/env-BZ0uy8XK.js +108 -0
- package/dist/cli/env-jIFUADLY.js +511 -0
- package/dist/cli/errors-4v4DTtda.js +56 -0
- package/dist/cli/fastest-levenshtein-CFN-lNDv.js +120 -0
- package/dist/cli/gen-Ccn_p90L.js +2008 -0
- package/dist/cli/gen-D5cLCULx.js +2 -0
- package/dist/cli/index.d.ts +295 -28
- package/dist/cli/index.js +184 -3
- package/dist/cli/init-ClnxRYBF.js +550 -0
- package/dist/cli/introspect-DxqfkVIv.js +81 -0
- package/dist/cli/io-k41_z-jT.js +24 -0
- package/dist/cli/json5-ChRycquj.js +787 -0
- package/dist/cli/jsonc-BUniUpOk.js +2 -0
- package/dist/cli/jsonc-D5Fu67jw.js +45 -0
- package/dist/cli/keys-ByKHnvP9.js +83 -0
- package/dist/cli/ohash-D7bG_EOb.js +277 -0
- package/dist/cli/openapi-8WHjxiTJ.js +66 -0
- package/dist/cli/project-B_GeXyHh.js +70 -0
- package/dist/cli/prompts-BNcNfAve.js +1142 -0
- package/dist/cli/prompts-BTYQGunc.js +2 -0
- package/dist/cli/read-sets-CMa29t9a.js +971 -0
- package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
- package/dist/cli/run-CP20LKk_.js +347 -0
- package/dist/cli/seed-5J6eu_Xg.js +98 -0
- package/dist/cli/skills-LJJIhLFR.js +137 -0
- package/dist/cli/sql-D4VbqmXi.js +199 -0
- package/dist/cli/style-C0NFdJRL.js +29 -0
- package/dist/cli/toml-DB-MNnFs.js +424 -0
- package/dist/{version-Cqq1m3UY.js → cli/version-5mW_8sY1.js} +1 -1
- package/dist/cli/yaml-CYCbJ6et.js +2252 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +15 -25
- package/dist/{compiler-CZ9nIuqy.d.ts → compiler-DB3aSFOA.d.ts} +2 -2
- package/dist/config/index.d.ts +4 -3
- package/dist/config/index.js +5 -3
- package/dist/config-BpxDfnbg.js +129 -0
- package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
- package/dist/{config-ClDXmVtY.js → config-CbvFmGD8.js} +14 -137
- package/dist/{define-BXMYD9AY.js → define-Bh0AqTik.js} +221 -120
- package/dist/{define-e3zI4_4g.d.ts → define-CRS2MRV3.d.ts} +36 -31
- package/dist/edge/index.d.ts +9 -13
- package/dist/edge/index.js +51 -25
- package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-Dm-FHpNH.d.ts} +2 -2
- package/dist/env/index.js +203 -1
- package/dist/{errors-Bl3rkOzo.js → errors-L0xK41y_.js} +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.js +139 -1
- package/dist/{events-DOt3nSO-.d.ts → events-B21UOhvP.d.ts} +4 -4
- package/dist/{executor-CGdNQ27g.d.ts → executor-B5IoUxLE.d.ts} +2 -2
- package/dist/{executor-DeppvirK.js → executor-CVt6dD0B.js} +9 -4
- package/dist/{executor-BYXQ9AGn.d.ts → executor-CZ7ImRiD.d.ts} +2 -2
- package/dist/hono/index.d.ts +17 -24
- package/dist/hono/index.js +11 -11
- package/dist/{index-DuP14VHo.d.ts → index-528Ugmyp.d.ts} +30 -10
- package/dist/{index-Bw1bwtC0.d.ts → index-BAy4tsAP.d.ts} +28 -15
- package/dist/{index-CBDufH1M.d.ts → index-BBdvo-5d.d.ts} +24 -26
- package/dist/{index-DbxFr7XG.d.ts → index-BhHEC04r.d.ts} +9 -4
- package/dist/index-Cf-D2jk1.d.ts +50 -0
- package/dist/{index-Ciu5Xlml.d.ts → index-D5IfUIDh.d.ts} +6 -5
- package/dist/{index-K-3WM2Hp.d.ts → index-DFmOpBGC.d.ts} +13 -13
- package/dist/{index-D4v7sncu.d.ts → index-RlLXd8dL.d.ts} +13 -13
- package/dist/index.d.ts +17 -17
- package/dist/index.js +23 -14
- package/dist/{invalidate-DbxuL2jL.js → invalidate-CgxmRamI.js} +7 -1
- package/dist/jobs/index.d.ts +33 -26
- package/dist/jobs/index.js +44 -22
- package/dist/{json-schema-BpYqkCKf.js → json-schema-DP6V7cbr.js} +8 -3
- package/dist/lint/index.js +1 -1
- package/dist/list/index.d.ts +2 -2
- package/dist/list/index.js +131 -96
- package/dist/{live-DJyZMD6w.d.ts → live-BHakSWWo.d.ts} +26 -16
- package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
- package/dist/lookup-BaP5bI27.js +18 -0
- package/dist/mcp/index.d.ts +34 -27
- package/dist/mcp/index.js +59 -25
- package/dist/{mfa-TVia554c.d.ts → mfa-C7MNQ1Ob.d.ts} +1 -1
- package/dist/{mfa-CpLfJSde.js → mfa-byfjruR9.js} +190 -46
- package/dist/next/image/index.js +6 -3
- package/dist/next/index.d.ts +64 -48
- package/dist/next/index.js +63 -50
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +61 -38
- package/dist/orpc/index.d.ts +18 -21
- package/dist/orpc/index.js +12 -12
- package/dist/otel/index.d.ts +5 -5
- package/dist/otel/index.js +84 -63
- package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-C4KFzLc9.js} +12 -7
- package/dist/permdock-sql-DImJULY-.d.ts +17 -0
- package/dist/{plugin-C4TR9J0Z.d.ts → plugin-bNhvJwRh.d.ts} +5 -4
- package/dist/plugins/actor/index.d.ts +1 -1
- package/dist/plugins/actor/index.js +1 -1
- package/dist/plugins/rules/index.d.ts +2 -2
- package/dist/plugins/rules/index.js +46 -16
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +4 -4
- package/dist/plugins/tenant/index.d.ts +3 -3
- package/dist/plugins/tenant/index.js +10 -4
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +2 -2
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +3 -3
- package/dist/pool-DFwEQwmN.d.ts +78 -0
- package/dist/postgres/index.d.ts +10 -5
- package/dist/postgres/index.js +37 -16
- package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-Bc-0Xw62.d.ts} +1 -1
- package/dist/{problem-BTkTtRV9.js → problem-BihjPR0t.js} +11 -5
- package/dist/{problem-DlgB0lYl.d.ts → problem-U8UEKccv.d.ts} +6 -4
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +2 -2
- package/dist/{query-ChvDbsDE.js → query-BMMSWbI7.js} +19 -19
- package/dist/react/index.d.ts +7 -7
- package/dist/react/index.js +2 -2
- package/dist/react/server.d.ts +6 -6
- package/dist/react/server.js +3 -3
- package/dist/react/session.d.ts +21 -2
- package/dist/react/session.js +19 -1
- package/dist/{react-C83BdBGt.js → react-CQHMaESR.js} +59 -55
- package/dist/{read-set-4lI3W_gZ.js → read-set-FWK8qQ58.js} +51 -16
- package/dist/realtime/index.d.ts +4 -3
- package/dist/realtime/index.js +19 -17
- package/dist/{index-CG69s15v.d.ts → refresh-BwYkyNOQ.d.ts} +7 -3
- package/dist/{resolve-CjHILk2w.d.ts → resolve-BAqQcwMW.d.ts} +17 -11
- package/dist/{resource-CgZa3YG_.d.ts → resource-BJcaIfxi.d.ts} +17 -8
- package/dist/{resource-BHEWmQJK.js → resource-My_y-Syh.js} +43 -21
- package/dist/{respond-Dne1ARSa.d.ts → respond-DgIbdrt8.d.ts} +39 -14
- package/dist/{result-DWXatkd6.js → result-Bj6yt33D.js} +2 -2
- package/dist/{result-CTkCZ6JA.d.ts → result-CqEsbgYs.d.ts} +16 -11
- package/dist/server/index.d.ts +38 -13
- package/dist/server/index.js +43 -14
- package/dist/{respond-DMcbQwfN.js → server-BA75B0mT.js} +151 -96
- package/dist/{shared-_6-uPL7E.js → shared-DnoCdMDr.js} +4 -3
- package/dist/{simplify-bwJpLnaS.js → simplify-Cqvfr9dj.js} +76 -39
- package/dist/sql/index.d.ts +139 -0
- package/dist/sql/index.js +1983 -0
- package/dist/{sql-DTjA1LPj.js → sql-B34HU2DI.js} +74 -17
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.js +2 -2
- package/dist/{standard-FUi3Z3-7.js → standard-BRyBGTtp.js} +2 -2
- package/dist/{standard-CyhRzctb.d.ts → standard-BsaCYQJc.d.ts} +1 -1
- package/dist/{stats-C5W-rBfR.js → stats-C_YxA2r1.js} +40 -14
- package/dist/storage/index.d.ts +4 -3
- package/dist/storage/index.js +548 -1
- package/dist/{tables-rZxRxNPW.js → tables-Cb-3_VWc.js} +19 -5
- package/dist/temporal-BwshQk0W.js +27 -0
- package/dist/temporal-required-CBNHT6ni.js +19 -0
- package/dist/testing/index.d.ts +25 -24
- package/dist/testing/index.js +165 -66
- package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
- package/dist/version-Bmf7_FzM.js +4 -0
- package/dist/{view-D1s0wa0T.d.ts → view-B64o81wp.d.ts} +36 -6
- package/dist/{view-aOYizTeE.js → view-BrJI2LKp.js} +11 -2
- package/dist/webhooks/index.d.ts +19 -17
- package/dist/webhooks/index.js +1 -1
- package/dist/{webhooks-DMipjhSP.js → webhooks-Bh_Jf_-l.js} +45 -24
- package/package.json +50 -22
- package/schemas/config-v1.json +31 -1
- package/schemas/doctor-report-v1.json +17 -1
- package/schemas/snapshot-v2.json +35 -0
- package/skills/better-supabase/SKILL.md +77 -18
- package/skills/better-supabase/references/plugins.md +21 -22
- package/skills/better-supabase/references/troubleshooting.md +38 -18
- package/skills/better-supabase-api/SKILL.md +66 -18
- package/skills/better-supabase-api/references/adapters.md +64 -41
- package/skills/better-supabase-auth/SKILL.md +146 -0
- package/skills/better-supabase-auth/references/permdock.md +55 -0
- package/skills/better-supabase-testing/SKILL.md +68 -11
- package/dist/casing-da0uRTqt.js +0 -14
- package/dist/claims-CoTobNC-.js +0 -25
- package/dist/cli-DrSgDOQC.js +0 -6646
- package/dist/env-BEToab0I.js +0 -204
- package/dist/events-BuzTgn2D.js +0 -135
- package/dist/pool-R2m_DkXi.d.ts +0 -37
- package/dist/seed-CzecODcJ.js +0 -101
- package/dist/session-C3LxnQ0e.d.ts +0 -22
- package/dist/session-CqEwzVup.js +0 -20
- package/dist/storage-DuGn38fr.js +0 -527
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { n as CliError } from "./errors-4v4DTtda.js";
|
|
2
|
+
import { g as url, l as pipe, p as string, s as optional } from "./dist-Du7VnEUG.js";
|
|
3
|
+
//#region ../../node_modules/.pnpm/@t3-oss+env-core@0.13.11_arktype@2.2.3_typescript@7.0.2_valibot@1.5.0_typescript@7.0.2__zod@4.6.5/node_modules/@t3-oss/env-core/dist/standard.js
|
|
4
|
+
function ensureSynchronous(value, message) {
|
|
5
|
+
if (value instanceof Promise) throw new Error(message);
|
|
6
|
+
}
|
|
7
|
+
function parseWithDictionary(dictionary, value) {
|
|
8
|
+
const result = {};
|
|
9
|
+
const issues = [];
|
|
10
|
+
for (const key in dictionary) {
|
|
11
|
+
const propResult = dictionary[key]["~standard"].validate(value[key]);
|
|
12
|
+
ensureSynchronous(propResult, `Validation must be synchronous, but ${key} returned a Promise.`);
|
|
13
|
+
if (propResult.issues) {
|
|
14
|
+
issues.push(...propResult.issues.map((issue) => ({
|
|
15
|
+
...issue,
|
|
16
|
+
message: issue.message,
|
|
17
|
+
path: [key, ...issue.path ?? []]
|
|
18
|
+
})));
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
result[key] = propResult.value;
|
|
22
|
+
}
|
|
23
|
+
if (issues.length) return { issues };
|
|
24
|
+
return { value: result };
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
//#region ../../node_modules/.pnpm/@t3-oss+env-core@0.13.11_arktype@2.2.3_typescript@7.0.2_valibot@1.5.0_typescript@7.0.2__zod@4.6.5/node_modules/@t3-oss/env-core/dist/index.js
|
|
28
|
+
/**
|
|
29
|
+
* Create a new environment variable schema.
|
|
30
|
+
*/
|
|
31
|
+
function createEnv(opts) {
|
|
32
|
+
const runtimeEnv = opts.runtimeEnvStrict ?? opts.runtimeEnv ?? process.env;
|
|
33
|
+
if (opts.emptyStringAsUndefined ?? false) {
|
|
34
|
+
for (const [key, value] of Object.entries(runtimeEnv)) if (value === "") delete runtimeEnv[key];
|
|
35
|
+
}
|
|
36
|
+
if (!!opts.skipValidation) {
|
|
37
|
+
if (opts.extends) for (const preset of opts.extends) preset.skipValidation = true;
|
|
38
|
+
return runtimeEnv;
|
|
39
|
+
}
|
|
40
|
+
const _client = typeof opts.client === "object" ? opts.client : {};
|
|
41
|
+
const _server = typeof opts.server === "object" ? opts.server : {};
|
|
42
|
+
const _shared = typeof opts.shared === "object" ? opts.shared : {};
|
|
43
|
+
const isServer = opts.isServer ?? (typeof window === "undefined" || "Deno" in window);
|
|
44
|
+
const finalSchemaShape = isServer ? {
|
|
45
|
+
..._server,
|
|
46
|
+
..._shared,
|
|
47
|
+
..._client
|
|
48
|
+
} : {
|
|
49
|
+
..._client,
|
|
50
|
+
..._shared
|
|
51
|
+
};
|
|
52
|
+
const parsed = (opts.createFinalSchema?.(finalSchemaShape, isServer))?.["~standard"].validate(runtimeEnv) ?? parseWithDictionary(finalSchemaShape, runtimeEnv);
|
|
53
|
+
ensureSynchronous(parsed, "Validation must be synchronous");
|
|
54
|
+
const onValidationError = opts.onValidationError ?? ((issues) => {
|
|
55
|
+
console.error("❌ Invalid environment variables:", issues);
|
|
56
|
+
throw new Error("Invalid environment variables");
|
|
57
|
+
});
|
|
58
|
+
const onInvalidAccess = opts.onInvalidAccess ?? (() => {
|
|
59
|
+
throw new Error("❌ Attempted to access a server-side environment variable on the client");
|
|
60
|
+
});
|
|
61
|
+
if (parsed.issues) return onValidationError(parsed.issues);
|
|
62
|
+
const isServerAccess = (prop) => {
|
|
63
|
+
if (!opts.clientPrefix) return true;
|
|
64
|
+
return !prop.startsWith(opts.clientPrefix) && !(prop in _shared);
|
|
65
|
+
};
|
|
66
|
+
const isValidServerAccess = (prop) => {
|
|
67
|
+
return isServer || !isServerAccess(prop);
|
|
68
|
+
};
|
|
69
|
+
const ignoreProp = (prop) => {
|
|
70
|
+
return prop === "__esModule" || prop === "$$typeof";
|
|
71
|
+
};
|
|
72
|
+
const extendedObj = (opts.extends ?? []).reduce((acc, curr) => {
|
|
73
|
+
return Object.assign(acc, curr);
|
|
74
|
+
}, {});
|
|
75
|
+
const fullObj = Object.assign(extendedObj, parsed.value);
|
|
76
|
+
return new Proxy(fullObj, { get(target, prop) {
|
|
77
|
+
if (typeof prop !== "string") return void 0;
|
|
78
|
+
if (ignoreProp(prop)) return void 0;
|
|
79
|
+
if (!isValidServerAccess(prop)) return onInvalidAccess(prop);
|
|
80
|
+
return Reflect.get(target, prop);
|
|
81
|
+
} });
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region src/cli/env.ts
|
|
85
|
+
const optionalString = optional(string());
|
|
86
|
+
const optionalUrl = optional(pipe(string(), url("must be a URL, e.g. postgresql://user@host/db")));
|
|
87
|
+
/** Parses the variables the CLI reads; an invalid value is a `env_invalid` usage error. */
|
|
88
|
+
function parseEnv(env) {
|
|
89
|
+
return createEnv({
|
|
90
|
+
server: {
|
|
91
|
+
DATABASE_URL: optionalUrl,
|
|
92
|
+
SUPABASE_ACCESS_TOKEN: optionalString,
|
|
93
|
+
SUPABASE_API_URL: optionalUrl,
|
|
94
|
+
SUPABASE_BIN: optionalString,
|
|
95
|
+
HOME: optionalString,
|
|
96
|
+
CI: optionalString
|
|
97
|
+
},
|
|
98
|
+
runtimeEnv: env,
|
|
99
|
+
isServer: true,
|
|
100
|
+
emptyStringAsUndefined: true,
|
|
101
|
+
onValidationError: (issues) => {
|
|
102
|
+
const lines = issues.map((issue) => `${issue.path?.map((key) => String(typeof key === "object" ? key.key : key)).join(".") ?? "env"}: ${issue.message}`);
|
|
103
|
+
throw new CliError("env_invalid", `Invalid environment variable:\n${lines.map((line) => ` ${line}`).join("\n")}`, { issues: lines });
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
export { parseEnv };
|
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import { r as defineCliCommand } from "./command-CK14fP91.js";
|
|
2
|
+
import { r as writeIfChanged, t as display } from "./io-k41_z-jT.js";
|
|
3
|
+
import { r as publicPrefix, t as detectProject } from "./project-B_GeXyHh.js";
|
|
4
|
+
import { basename, delimiter, dirname, normalize, resolve } from "node:path";
|
|
5
|
+
import { closeSync, existsSync, openSync, readSync, statSync } from "node:fs";
|
|
6
|
+
import { readFile } from "node:fs/promises";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { cwd } from "node:process";
|
|
9
|
+
import l__default from "node:readline";
|
|
10
|
+
import { spawn } from "node:child_process";
|
|
11
|
+
import { pipeline } from "node:stream/promises";
|
|
12
|
+
import { PassThrough } from "node:stream";
|
|
13
|
+
//#region ../../node_modules/.pnpm/tinyexec@1.3.1/node_modules/tinyexec/dist/main.mjs
|
|
14
|
+
const isPathLikePattern = /^path$/i;
|
|
15
|
+
const defaultEnvPathInfo = {
|
|
16
|
+
key: "PATH",
|
|
17
|
+
value: ""
|
|
18
|
+
};
|
|
19
|
+
function getPathFromEnv(env) {
|
|
20
|
+
for (const key in env) {
|
|
21
|
+
if (!Object.prototype.hasOwnProperty.call(env, key) || !isPathLikePattern.test(key)) continue;
|
|
22
|
+
const value = env[key];
|
|
23
|
+
if (!value) return defaultEnvPathInfo;
|
|
24
|
+
return {
|
|
25
|
+
key,
|
|
26
|
+
value
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return defaultEnvPathInfo;
|
|
30
|
+
}
|
|
31
|
+
function addNodeBinToPath(cwd, path) {
|
|
32
|
+
const parts = path.value.split(delimiter);
|
|
33
|
+
const nodeBinPaths = [];
|
|
34
|
+
let currentPath = typeof cwd === "string" ? cwd : fileURLToPath(cwd, { windows: false });
|
|
35
|
+
let lastPath;
|
|
36
|
+
do {
|
|
37
|
+
nodeBinPaths.push(resolve(currentPath, "node_modules", ".bin"));
|
|
38
|
+
lastPath = currentPath;
|
|
39
|
+
currentPath = dirname(currentPath);
|
|
40
|
+
} while (currentPath !== lastPath);
|
|
41
|
+
nodeBinPaths.push(dirname(process.execPath));
|
|
42
|
+
const newPath = nodeBinPaths.concat(parts).join(delimiter);
|
|
43
|
+
return {
|
|
44
|
+
key: path.key,
|
|
45
|
+
value: newPath
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function computeEnv(cwd, env, nodePath = true) {
|
|
49
|
+
const envWithDefault = {
|
|
50
|
+
...process.env,
|
|
51
|
+
...env
|
|
52
|
+
};
|
|
53
|
+
if (!nodePath) return envWithDefault;
|
|
54
|
+
const envPathInfo = addNodeBinToPath(cwd, getPathFromEnv(envWithDefault));
|
|
55
|
+
envWithDefault[envPathInfo.key] = envPathInfo.value;
|
|
56
|
+
return envWithDefault;
|
|
57
|
+
}
|
|
58
|
+
const combineStreams = (streams) => {
|
|
59
|
+
let streamCount = streams.length;
|
|
60
|
+
const combined = new PassThrough();
|
|
61
|
+
const maybeEmitEnd = () => {
|
|
62
|
+
if (--streamCount === 0) combined.end();
|
|
63
|
+
};
|
|
64
|
+
for (const stream of streams) pipeline(stream, combined, { end: false }).then(maybeEmitEnd).catch(maybeEmitEnd);
|
|
65
|
+
return combined;
|
|
66
|
+
};
|
|
67
|
+
const metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
|
|
68
|
+
const shebangRegExp = /^#!\s*(.+)/;
|
|
69
|
+
const isWindowsExecutableRegExp = /\.(?:com|exe)$/i;
|
|
70
|
+
const isNodeModulesCmdRegExp = /node_modules[\\/]\.bin[\\/][^\\/]+\.cmd$/i;
|
|
71
|
+
const isWindows = process.platform === "win32";
|
|
72
|
+
const defaultPathExt = [
|
|
73
|
+
".EXE",
|
|
74
|
+
".CMD",
|
|
75
|
+
".BAT",
|
|
76
|
+
".COM"
|
|
77
|
+
];
|
|
78
|
+
const noPathExt = [""];
|
|
79
|
+
/**
|
|
80
|
+
* Normalizes the command and arguments to work cross-platform.
|
|
81
|
+
* On Windows, this basically handles things like shebangs, calling
|
|
82
|
+
* `node_modules/.bin` commands, and escaping meta characters.
|
|
83
|
+
* On other platforms, it just returns the command and arguments as-is.
|
|
84
|
+
*/
|
|
85
|
+
function normalizeSpawnCommand(command, args = [], options = {}) {
|
|
86
|
+
if (options.shell === true || !isWindows) return {
|
|
87
|
+
command,
|
|
88
|
+
args,
|
|
89
|
+
options
|
|
90
|
+
};
|
|
91
|
+
let file = resolveCommand(command, options);
|
|
92
|
+
let shebang = null;
|
|
93
|
+
if (file !== null) {
|
|
94
|
+
const size = 150;
|
|
95
|
+
const buffer = Buffer.alloc(size);
|
|
96
|
+
let fd = null;
|
|
97
|
+
try {
|
|
98
|
+
fd = openSync(file, "r");
|
|
99
|
+
readSync(fd, buffer, 0, size, 0);
|
|
100
|
+
} catch {} finally {
|
|
101
|
+
if (fd !== null) closeSync(fd);
|
|
102
|
+
}
|
|
103
|
+
const match = buffer.toString().match(shebangRegExp);
|
|
104
|
+
if (match !== null) {
|
|
105
|
+
const line = match[1].trim();
|
|
106
|
+
const separatorIndex = line.indexOf(" ");
|
|
107
|
+
const path = separatorIndex !== -1 ? line.slice(0, separatorIndex) : line;
|
|
108
|
+
const argument = separatorIndex !== -1 ? line.slice(separatorIndex + 1) : "";
|
|
109
|
+
const binary = basename(path);
|
|
110
|
+
shebang = binary === "env" ? argument || null : binary;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (shebang !== null && file !== null) {
|
|
114
|
+
args = [file, ...args];
|
|
115
|
+
command = shebang;
|
|
116
|
+
file = resolveCommand(command, options);
|
|
117
|
+
}
|
|
118
|
+
if (file === null || !isWindowsExecutableRegExp.test(file)) {
|
|
119
|
+
const needsDoubleEscapeMetaChars = file !== null && isNodeModulesCmdRegExp.test(file);
|
|
120
|
+
command = normalize(command);
|
|
121
|
+
command = command.replace(metaCharsRegExp, "^$1");
|
|
122
|
+
args = args.map((arg) => {
|
|
123
|
+
arg = arg.replace(/(?=(\\+?)?)\1"/g, "$1$1\\\"");
|
|
124
|
+
arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
|
|
125
|
+
arg = `"${arg}"`;
|
|
126
|
+
arg = arg.replace(metaCharsRegExp, "^$1");
|
|
127
|
+
if (needsDoubleEscapeMetaChars) arg = arg.replace(metaCharsRegExp, "^$1");
|
|
128
|
+
return arg;
|
|
129
|
+
});
|
|
130
|
+
args = [
|
|
131
|
+
"/d",
|
|
132
|
+
"/s",
|
|
133
|
+
"/c",
|
|
134
|
+
`"${[command, ...args].join(" ")}"`
|
|
135
|
+
];
|
|
136
|
+
command = options.env?.comspec ?? "cmd.exe";
|
|
137
|
+
options = {
|
|
138
|
+
...options,
|
|
139
|
+
windowsVerbatimArguments: true
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
return {
|
|
143
|
+
command,
|
|
144
|
+
args,
|
|
145
|
+
options
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Resolves the command to an absolute path if possible.
|
|
150
|
+
* Handles things like traversing PATH and adding extensions from PATHEXT
|
|
151
|
+
*/
|
|
152
|
+
function resolveCommand(command, options) {
|
|
153
|
+
const cwd$3 = (options.cwd ?? cwd()).toString();
|
|
154
|
+
const env = options.env ?? process.env;
|
|
155
|
+
const PATH = getPathFromEnv(env).value;
|
|
156
|
+
const pathEnv = command.includes("/") || command.includes("\\") ? [""] : [cwd$3, ...PATH.split(delimiter)];
|
|
157
|
+
let pathExt = env.PATHEXT ? env.PATHEXT.split(delimiter) : defaultPathExt;
|
|
158
|
+
if (command.includes(".") && pathExt[0] !== "") pathExt = ["", ...pathExt];
|
|
159
|
+
for (const extensions of [pathExt, noPathExt]) for (const path of pathEnv) {
|
|
160
|
+
const unquoted = path.startsWith("\"") && path.endsWith("\"") && path.length > 1 ? path.slice(1, -1) : path;
|
|
161
|
+
const dest = resolve(cwd$3, unquoted, command);
|
|
162
|
+
for (const ext of extensions) {
|
|
163
|
+
const destWithExt = dest + ext;
|
|
164
|
+
try {
|
|
165
|
+
if (statSync(destWithExt).isFile()) return destWithExt;
|
|
166
|
+
} catch {}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
var NonZeroExitError = class extends Error {
|
|
172
|
+
result;
|
|
173
|
+
output;
|
|
174
|
+
exitCode;
|
|
175
|
+
get signalCode() {
|
|
176
|
+
return this.result.signalCode;
|
|
177
|
+
}
|
|
178
|
+
constructor(result, output, command, args) {
|
|
179
|
+
let target = "The process";
|
|
180
|
+
if (command) target = `The command \`${args?.length ? `${command} ${args.map((a) => /[ "'`()]/.test(a) ? JSON.stringify(a) : a).join(" ")}` : command}\``;
|
|
181
|
+
const exitCode = result.exitCode ?? 1;
|
|
182
|
+
super(result.signalCode !== null ? `${target} was killed by the signal ${result.signalCode}` : `${target} exited with a non-zero status (${exitCode})`);
|
|
183
|
+
this.result = result;
|
|
184
|
+
this.output = output;
|
|
185
|
+
this.exitCode = exitCode;
|
|
186
|
+
Object.defineProperty(this, "result", {
|
|
187
|
+
enumerable: false,
|
|
188
|
+
writable: false,
|
|
189
|
+
configurable: false
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
const defaultOptions = {
|
|
194
|
+
timeout: void 0,
|
|
195
|
+
persist: false
|
|
196
|
+
};
|
|
197
|
+
const defaultNodeOptions = { windowsHide: true };
|
|
198
|
+
function combineSignals(signals) {
|
|
199
|
+
const controller = new AbortController();
|
|
200
|
+
for (const signal of signals) {
|
|
201
|
+
if (signal.aborted) {
|
|
202
|
+
controller.abort();
|
|
203
|
+
return signal;
|
|
204
|
+
}
|
|
205
|
+
const onAbort = () => {
|
|
206
|
+
controller.abort(signal.reason);
|
|
207
|
+
};
|
|
208
|
+
signal.addEventListener("abort", onAbort, { signal: controller.signal });
|
|
209
|
+
}
|
|
210
|
+
return controller.signal;
|
|
211
|
+
}
|
|
212
|
+
async function readStream(stream) {
|
|
213
|
+
let output = "";
|
|
214
|
+
try {
|
|
215
|
+
for await (const chunk of stream) output += chunk.toString();
|
|
216
|
+
} catch {}
|
|
217
|
+
return output;
|
|
218
|
+
}
|
|
219
|
+
var ExecProcess = class {
|
|
220
|
+
_process;
|
|
221
|
+
_aborted = false;
|
|
222
|
+
_options;
|
|
223
|
+
_command;
|
|
224
|
+
_args;
|
|
225
|
+
_resolveClose;
|
|
226
|
+
_processClosed;
|
|
227
|
+
_thrownError;
|
|
228
|
+
get process() {
|
|
229
|
+
return this._process;
|
|
230
|
+
}
|
|
231
|
+
get pid() {
|
|
232
|
+
return this._process?.pid;
|
|
233
|
+
}
|
|
234
|
+
get exitCode() {
|
|
235
|
+
if (this._process && this._process.exitCode !== null) return this._process.exitCode;
|
|
236
|
+
}
|
|
237
|
+
get signalCode() {
|
|
238
|
+
return this._process?.signalCode ?? null;
|
|
239
|
+
}
|
|
240
|
+
constructor(command, args, options) {
|
|
241
|
+
this._options = {
|
|
242
|
+
...defaultOptions,
|
|
243
|
+
...options
|
|
244
|
+
};
|
|
245
|
+
this._command = command;
|
|
246
|
+
this._args = args ?? [];
|
|
247
|
+
this._processClosed = new Promise((resolve) => {
|
|
248
|
+
this._resolveClose = resolve;
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
kill(signal) {
|
|
252
|
+
return this._process?.kill(signal) === true;
|
|
253
|
+
}
|
|
254
|
+
get aborted() {
|
|
255
|
+
return this._aborted;
|
|
256
|
+
}
|
|
257
|
+
get killed() {
|
|
258
|
+
return this._process?.killed === true;
|
|
259
|
+
}
|
|
260
|
+
pipe(command, args, options) {
|
|
261
|
+
return exec$1(command, args, {
|
|
262
|
+
...options,
|
|
263
|
+
stdin: this
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
async *[Symbol.asyncIterator]() {
|
|
267
|
+
const proc = this._process;
|
|
268
|
+
if (!proc) return;
|
|
269
|
+
const streams = [];
|
|
270
|
+
if (this._streamErr) streams.push(this._streamErr);
|
|
271
|
+
if (this._streamOut) streams.push(this._streamOut);
|
|
272
|
+
const streamCombined = combineStreams(streams);
|
|
273
|
+
const rl = l__default.createInterface({ input: streamCombined });
|
|
274
|
+
for await (const chunk of rl) yield chunk.toString();
|
|
275
|
+
await this._processClosed;
|
|
276
|
+
proc.removeAllListeners();
|
|
277
|
+
if (this._thrownError) throw this._thrownError;
|
|
278
|
+
if (this._options?.throwOnError && (this.exitCode !== 0 && this.exitCode !== void 0 || this.signalCode !== null)) throw new NonZeroExitError(this, void 0, this._command, this._args);
|
|
279
|
+
}
|
|
280
|
+
async _waitForOutput() {
|
|
281
|
+
const proc = this._process;
|
|
282
|
+
if (!proc) throw new Error("No process was started");
|
|
283
|
+
const [stdout, stderr] = await Promise.all([this._streamOut ? readStream(this._streamOut) : "", this._streamErr ? readStream(this._streamErr) : ""]);
|
|
284
|
+
await this._processClosed;
|
|
285
|
+
const { stdin } = this._options;
|
|
286
|
+
if (stdin && typeof stdin !== "string") await stdin;
|
|
287
|
+
proc.removeAllListeners();
|
|
288
|
+
if (this._thrownError) throw this._thrownError;
|
|
289
|
+
const result = {
|
|
290
|
+
stderr,
|
|
291
|
+
stdout,
|
|
292
|
+
exitCode: this.exitCode
|
|
293
|
+
};
|
|
294
|
+
if (this._options.throwOnError && (this.exitCode !== 0 && this.exitCode !== void 0 || this.signalCode !== null)) throw new NonZeroExitError(this, result, this._command, this._args);
|
|
295
|
+
return result;
|
|
296
|
+
}
|
|
297
|
+
then(onfulfilled, onrejected) {
|
|
298
|
+
return this._waitForOutput().then(onfulfilled, onrejected);
|
|
299
|
+
}
|
|
300
|
+
_streamOut;
|
|
301
|
+
_streamErr;
|
|
302
|
+
spawn() {
|
|
303
|
+
const options = this._options;
|
|
304
|
+
const nodeOptions = {
|
|
305
|
+
...defaultNodeOptions,
|
|
306
|
+
...options.nodeOptions
|
|
307
|
+
};
|
|
308
|
+
const cwd$1 = nodeOptions?.cwd ?? cwd();
|
|
309
|
+
const signals = [];
|
|
310
|
+
this._resetState();
|
|
311
|
+
if (options.timeout !== void 0) signals.push(AbortSignal.timeout(options.timeout));
|
|
312
|
+
if (options.signal !== void 0) signals.push(options.signal);
|
|
313
|
+
if (options.persist === true) nodeOptions.detached = true;
|
|
314
|
+
if (signals.length > 0) nodeOptions.signal = combineSignals(signals);
|
|
315
|
+
nodeOptions.env = computeEnv(cwd$1, nodeOptions.env, options.nodePath);
|
|
316
|
+
const crossResult = normalizeSpawnCommand(this._command, this._args, nodeOptions);
|
|
317
|
+
const handle = spawn(crossResult.command, crossResult.args, crossResult.options);
|
|
318
|
+
if (handle.stderr) this._streamErr = handle.stderr;
|
|
319
|
+
if (handle.stdout) this._streamOut = handle.stdout;
|
|
320
|
+
this._process = handle;
|
|
321
|
+
handle.once("error", this._onError);
|
|
322
|
+
handle.once("close", this._onClose);
|
|
323
|
+
if (handle.stdin) {
|
|
324
|
+
const { stdin } = options;
|
|
325
|
+
if (typeof stdin === "string") handle.stdin.end(stdin);
|
|
326
|
+
else stdin?.process?.stdout?.pipe(handle.stdin);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
_resetState() {
|
|
330
|
+
this._aborted = false;
|
|
331
|
+
this._processClosed = new Promise((resolve) => {
|
|
332
|
+
this._resolveClose = resolve;
|
|
333
|
+
});
|
|
334
|
+
this._thrownError = void 0;
|
|
335
|
+
}
|
|
336
|
+
_onError = (err) => {
|
|
337
|
+
if (err.name === "AbortError" && (!(err.cause instanceof Error) || err.cause.name !== "TimeoutError")) {
|
|
338
|
+
this._aborted = true;
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
this._thrownError = err;
|
|
342
|
+
};
|
|
343
|
+
_onClose = () => {
|
|
344
|
+
if (this._resolveClose) this._resolveClose();
|
|
345
|
+
};
|
|
346
|
+
};
|
|
347
|
+
const x = (command, args, userOptions) => {
|
|
348
|
+
const proc = new ExecProcess(command, args, userOptions);
|
|
349
|
+
proc.spawn();
|
|
350
|
+
return proc;
|
|
351
|
+
};
|
|
352
|
+
const exec$1 = x;
|
|
353
|
+
//#endregion
|
|
354
|
+
//#region src/cli/exec.ts
|
|
355
|
+
async function exec(command, args, cwd) {
|
|
356
|
+
try {
|
|
357
|
+
const result = await x(command, [...args], {
|
|
358
|
+
nodeOptions: {
|
|
359
|
+
cwd,
|
|
360
|
+
stdio: [
|
|
361
|
+
"ignore",
|
|
362
|
+
"pipe",
|
|
363
|
+
"pipe"
|
|
364
|
+
]
|
|
365
|
+
},
|
|
366
|
+
throwOnError: false
|
|
367
|
+
});
|
|
368
|
+
return {
|
|
369
|
+
code: result.exitCode ?? 1,
|
|
370
|
+
stdout: result.stdout,
|
|
371
|
+
stderr: result.stderr
|
|
372
|
+
};
|
|
373
|
+
} catch (error) {
|
|
374
|
+
return {
|
|
375
|
+
code: 127,
|
|
376
|
+
stdout: "",
|
|
377
|
+
stderr: error instanceof Error ? error.message : String(error)
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
/** Runs the Supabase CLI: `$SUPABASE_BIN`, then `supabase`, then `npx supabase`. */
|
|
382
|
+
async function supabaseCli(args, cwd, env) {
|
|
383
|
+
const result = await exec(env.SUPABASE_BIN ?? "supabase", args, cwd);
|
|
384
|
+
if (result.code !== 127) return result;
|
|
385
|
+
return exec("npx", [
|
|
386
|
+
"--yes",
|
|
387
|
+
"supabase",
|
|
388
|
+
...args
|
|
389
|
+
], cwd);
|
|
390
|
+
}
|
|
391
|
+
//#endregion
|
|
392
|
+
//#region src/cli/commands/env.ts
|
|
393
|
+
const ARGS = {
|
|
394
|
+
out: {
|
|
395
|
+
type: "string",
|
|
396
|
+
description: "Env file to write. Defaults to .env.local",
|
|
397
|
+
valueHint: "file"
|
|
398
|
+
},
|
|
399
|
+
prefix: {
|
|
400
|
+
type: "string",
|
|
401
|
+
description: "Prefix for browser variables, detected from your framework; \"none\" for no prefix",
|
|
402
|
+
valueHint: "prefix"
|
|
403
|
+
},
|
|
404
|
+
from: {
|
|
405
|
+
type: "string",
|
|
406
|
+
description: "Read `supabase status -o json` output from a file",
|
|
407
|
+
valueHint: "file"
|
|
408
|
+
},
|
|
409
|
+
print: {
|
|
410
|
+
type: "boolean",
|
|
411
|
+
description: "Print the variables instead of writing them"
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
async function readStatus(config, args, env) {
|
|
415
|
+
const from = args.from;
|
|
416
|
+
if (from) return JSON.parse(await readFile(resolve(config.root, from), "utf8"));
|
|
417
|
+
let result = await supabaseCli([
|
|
418
|
+
"status",
|
|
419
|
+
"-o",
|
|
420
|
+
"json"
|
|
421
|
+
], config.root, env);
|
|
422
|
+
if (result.code !== 0) {
|
|
423
|
+
const native = await supabaseCli([
|
|
424
|
+
"status",
|
|
425
|
+
"--env",
|
|
426
|
+
"--output-format",
|
|
427
|
+
"json"
|
|
428
|
+
], config.root, env);
|
|
429
|
+
if (native.code === 0) result = native;
|
|
430
|
+
}
|
|
431
|
+
if (result.code !== 0) throw new Error(`supabase status failed (${result.code}). Is the local stack running (supabase start)?`);
|
|
432
|
+
const start = result.stdout.indexOf("{");
|
|
433
|
+
if (start === -1) throw new Error("supabase status printed no JSON.");
|
|
434
|
+
return JSON.parse(result.stdout.slice(start));
|
|
435
|
+
}
|
|
436
|
+
const text = (status, ...keys) => {
|
|
437
|
+
for (const key of keys) {
|
|
438
|
+
const value = status[key];
|
|
439
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
/** Replaces `KEY=` lines in place and appends the rest under a header. */
|
|
443
|
+
function mergeEnv(current, values) {
|
|
444
|
+
const pending = new Map(Object.entries(values));
|
|
445
|
+
const merged = (current.length > 0 ? current.replace(/\n$/, "").split("\n") : []).map((line) => {
|
|
446
|
+
const key = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(line)?.[1];
|
|
447
|
+
if (!key || !pending.has(key)) return line;
|
|
448
|
+
const value = pending.get(key);
|
|
449
|
+
pending.delete(key);
|
|
450
|
+
return `${key}=${value}`;
|
|
451
|
+
});
|
|
452
|
+
if (pending.size > 0) {
|
|
453
|
+
if (merged.length > 0 && merged.at(-1) !== "") merged.push("");
|
|
454
|
+
merged.push("# Local Supabase stack (better-supabase env)");
|
|
455
|
+
for (const [key, value] of pending) merged.push(`${key}=${value}`);
|
|
456
|
+
}
|
|
457
|
+
return `${merged.join("\n")}\n`;
|
|
458
|
+
}
|
|
459
|
+
async function runEnv(config, args, env) {
|
|
460
|
+
const status = await readStatus(config, args, env);
|
|
461
|
+
const project = await detectProject(config.root);
|
|
462
|
+
const prefixFlag = args.prefix;
|
|
463
|
+
const prefix = prefixFlag === void 0 ? publicPrefix(project) : prefixFlag === "none" ? "" : prefixFlag;
|
|
464
|
+
const url = text(status, "API_URL");
|
|
465
|
+
const publishableKey = text(status, "PUBLISHABLE_KEY", "ANON_KEY");
|
|
466
|
+
const secretKey = text(status, "SECRET_KEY", "SERVICE_ROLE_KEY");
|
|
467
|
+
if (!url || !publishableKey) return {
|
|
468
|
+
code: 1,
|
|
469
|
+
error: "supabase status has no API_URL or publishable key. Is the stack running?"
|
|
470
|
+
};
|
|
471
|
+
const values = {
|
|
472
|
+
[`${prefix}SUPABASE_URL`]: url,
|
|
473
|
+
[`${prefix}SUPABASE_PUBLISHABLE_KEY`]: publishableKey
|
|
474
|
+
};
|
|
475
|
+
if (secretKey) values["SUPABASE_SECRET_KEY"] = secretKey;
|
|
476
|
+
const dbUrl = text(status, "DB_URL");
|
|
477
|
+
if (dbUrl) values["SUPABASE_DB_URL"] = dbUrl;
|
|
478
|
+
const jwtSecret = text(status, "JWT_SECRET");
|
|
479
|
+
if (jwtSecret) values["SUPABASE_JWT_SECRET"] = jwtSecret;
|
|
480
|
+
if (args.print === true) return {
|
|
481
|
+
code: 0,
|
|
482
|
+
output: Object.entries(values).map(([key, value]) => `${key}=${value}`).join("\n")
|
|
483
|
+
};
|
|
484
|
+
const out = args.out ?? ".env.local";
|
|
485
|
+
const path = resolve(config.root, out);
|
|
486
|
+
const current = existsSync(path) ? await readFile(path, "utf8") : "";
|
|
487
|
+
const lines = [`${await writeIfChanged(path, mergeEnv(current, values)) ? "Wrote" : "Unchanged"} ${display(config.root, out)}: ${Object.keys(values).join(", ")}`];
|
|
488
|
+
if (!text(status, "PUBLISHABLE_KEY")) lines.push("Warning: this Supabase CLI prints only legacy JWT keys. Upgrade it to get sb_publishable_/sb_secret_ keys.");
|
|
489
|
+
const gitignore = resolve(config.root, ".gitignore");
|
|
490
|
+
if (!(existsSync(gitignore) && (await readFile(gitignore, "utf8")).split("\n").some((line) => [
|
|
491
|
+
out,
|
|
492
|
+
`/${out}`,
|
|
493
|
+
".env*",
|
|
494
|
+
".env*.local",
|
|
495
|
+
"*.local"
|
|
496
|
+
].includes(line.trim())))) lines.push(`Warning: add ${out} to .gitignore; it contains the secret key.`);
|
|
497
|
+
return {
|
|
498
|
+
code: 0,
|
|
499
|
+
output: lines.join("\n")
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
const envCommand = defineCliCommand({
|
|
503
|
+
meta: {
|
|
504
|
+
name: "env",
|
|
505
|
+
description: "Writes the local stack's URL and keys from `supabase status` to an env file, keeping its other lines"
|
|
506
|
+
},
|
|
507
|
+
args: ARGS,
|
|
508
|
+
run: (args, { config, env }) => runEnv(config, args, env)
|
|
509
|
+
});
|
|
510
|
+
//#endregion
|
|
511
|
+
export { envCommand };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//#region src/cli/errors.ts
|
|
2
|
+
/** Each code has a heading on this page, so `type` links to its explanation. */
|
|
3
|
+
const CLI_ERRORS_URL = "https://bettersupabase.com/docs/cli/errors";
|
|
4
|
+
const TITLES = {
|
|
5
|
+
usage: "Invalid arguments",
|
|
6
|
+
unknown_command: "Unknown command",
|
|
7
|
+
missing_value: "Missing value",
|
|
8
|
+
config_not_found: "Config file not found",
|
|
9
|
+
config_invalid: "Invalid config",
|
|
10
|
+
env_invalid: "Invalid environment variable",
|
|
11
|
+
failed: "Command failed",
|
|
12
|
+
internal: "Unexpected error"
|
|
13
|
+
};
|
|
14
|
+
const EXIT_CODES = {
|
|
15
|
+
usage: 2,
|
|
16
|
+
unknown_command: 2,
|
|
17
|
+
missing_value: 2,
|
|
18
|
+
config_not_found: 2,
|
|
19
|
+
config_invalid: 2,
|
|
20
|
+
env_invalid: 2,
|
|
21
|
+
failed: 1,
|
|
22
|
+
internal: 1
|
|
23
|
+
};
|
|
24
|
+
/** An error the CLI reports as text, or as Problem Details under `--json`. */
|
|
25
|
+
var CliError = class extends Error {
|
|
26
|
+
name = "CliError";
|
|
27
|
+
code;
|
|
28
|
+
exitCode;
|
|
29
|
+
problem;
|
|
30
|
+
constructor(code, message, options = {}) {
|
|
31
|
+
super(message, options.cause === void 0 ? {} : { cause: options.cause });
|
|
32
|
+
const { exitCode = EXIT_CODES[code], cause: _cause, ...extensions } = options;
|
|
33
|
+
this.code = code;
|
|
34
|
+
this.exitCode = exitCode;
|
|
35
|
+
this.problem = {
|
|
36
|
+
type: `${CLI_ERRORS_URL}#${code}`,
|
|
37
|
+
title: TITLES[code],
|
|
38
|
+
detail: message,
|
|
39
|
+
code,
|
|
40
|
+
exitCode,
|
|
41
|
+
...extensions
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
/** citty's own argument errors. */
|
|
46
|
+
function isCittyUsageError(cause) {
|
|
47
|
+
return cause instanceof Error && cause.name === "CLIError";
|
|
48
|
+
}
|
|
49
|
+
/** Any thrown value as a `CliError`: citty's argument errors become `usage`, the rest `internal`. */
|
|
50
|
+
function toCliError(cause) {
|
|
51
|
+
if (cause instanceof CliError) return cause;
|
|
52
|
+
if (isCittyUsageError(cause)) return new CliError("usage", cause.message);
|
|
53
|
+
return new CliError("internal", cause instanceof Error ? cause.message : String(cause), { cause });
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { CliError as n, toCliError as r, CLI_ERRORS_URL as t };
|