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.
Files changed (190) hide show
  1. package/README.md +37 -33
  2. package/dist/base64-D2gsioCY.js +42 -0
  3. package/dist/claims-BAf6c7is.js +48 -0
  4. package/dist/cli/_format-Cax5EsM9.js +101 -0
  5. package/dist/cli/bin.js +39 -6
  6. package/dist/cli/command-CK14fP91.js +502 -0
  7. package/dist/cli/compare-BmIWVEui.js +9 -0
  8. package/dist/cli/config-D9R0o1LH.js +1895 -0
  9. package/dist/cli/config-SSKSTUl2.js +2 -0
  10. package/dist/cli/db-DOBPt660.js +52 -0
  11. package/dist/cli/dist-B1MvLv-M.js +129 -0
  12. package/dist/cli/dist-CFgGknmZ.js +1112 -0
  13. package/dist/cli/dist-Du7VnEUG.js +621 -0
  14. package/dist/cli/doctor-BOym3mbL.js +2382 -0
  15. package/dist/cli/env-BZ0uy8XK.js +108 -0
  16. package/dist/cli/env-jIFUADLY.js +511 -0
  17. package/dist/cli/errors-4v4DTtda.js +56 -0
  18. package/dist/cli/fastest-levenshtein-CFN-lNDv.js +120 -0
  19. package/dist/cli/gen-Ccn_p90L.js +2008 -0
  20. package/dist/cli/gen-D5cLCULx.js +2 -0
  21. package/dist/cli/index.d.ts +295 -28
  22. package/dist/cli/index.js +184 -3
  23. package/dist/cli/init-ClnxRYBF.js +550 -0
  24. package/dist/cli/introspect-DxqfkVIv.js +81 -0
  25. package/dist/cli/io-k41_z-jT.js +24 -0
  26. package/dist/cli/json5-ChRycquj.js +787 -0
  27. package/dist/cli/jsonc-BUniUpOk.js +2 -0
  28. package/dist/cli/jsonc-D5Fu67jw.js +45 -0
  29. package/dist/cli/keys-ByKHnvP9.js +83 -0
  30. package/dist/cli/ohash-D7bG_EOb.js +277 -0
  31. package/dist/cli/openapi-8WHjxiTJ.js +66 -0
  32. package/dist/cli/project-B_GeXyHh.js +70 -0
  33. package/dist/cli/prompts-BNcNfAve.js +1142 -0
  34. package/dist/cli/prompts-BTYQGunc.js +2 -0
  35. package/dist/cli/read-sets-CMa29t9a.js +971 -0
  36. package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
  37. package/dist/cli/run-CP20LKk_.js +347 -0
  38. package/dist/cli/seed-5J6eu_Xg.js +98 -0
  39. package/dist/cli/skills-LJJIhLFR.js +137 -0
  40. package/dist/cli/sql-D4VbqmXi.js +199 -0
  41. package/dist/cli/style-C0NFdJRL.js +29 -0
  42. package/dist/cli/toml-DB-MNnFs.js +424 -0
  43. package/dist/{version-Cqq1m3UY.js → cli/version-5mW_8sY1.js} +1 -1
  44. package/dist/cli/yaml-CYCbJ6et.js +2252 -0
  45. package/dist/client/index.d.ts +2 -2
  46. package/dist/client/index.js +15 -25
  47. package/dist/{compiler-CZ9nIuqy.d.ts → compiler-DB3aSFOA.d.ts} +2 -2
  48. package/dist/config/index.d.ts +4 -3
  49. package/dist/config/index.js +5 -3
  50. package/dist/config-BpxDfnbg.js +129 -0
  51. package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
  52. package/dist/{config-ClDXmVtY.js → config-CbvFmGD8.js} +14 -137
  53. package/dist/{define-BXMYD9AY.js → define-Bh0AqTik.js} +221 -120
  54. package/dist/{define-e3zI4_4g.d.ts → define-CRS2MRV3.d.ts} +36 -31
  55. package/dist/edge/index.d.ts +9 -13
  56. package/dist/edge/index.js +51 -25
  57. package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-Dm-FHpNH.d.ts} +2 -2
  58. package/dist/env/index.js +203 -1
  59. package/dist/{errors-Bl3rkOzo.js → errors-L0xK41y_.js} +1 -1
  60. package/dist/events/index.d.ts +1 -1
  61. package/dist/events/index.js +139 -1
  62. package/dist/{events-DOt3nSO-.d.ts → events-B21UOhvP.d.ts} +4 -4
  63. package/dist/{executor-CGdNQ27g.d.ts → executor-B5IoUxLE.d.ts} +2 -2
  64. package/dist/{executor-DeppvirK.js → executor-CVt6dD0B.js} +9 -4
  65. package/dist/{executor-BYXQ9AGn.d.ts → executor-CZ7ImRiD.d.ts} +2 -2
  66. package/dist/hono/index.d.ts +17 -24
  67. package/dist/hono/index.js +11 -11
  68. package/dist/{index-DuP14VHo.d.ts → index-528Ugmyp.d.ts} +30 -10
  69. package/dist/{index-Bw1bwtC0.d.ts → index-BAy4tsAP.d.ts} +28 -15
  70. package/dist/{index-CBDufH1M.d.ts → index-BBdvo-5d.d.ts} +24 -26
  71. package/dist/{index-DbxFr7XG.d.ts → index-BhHEC04r.d.ts} +9 -4
  72. package/dist/index-Cf-D2jk1.d.ts +50 -0
  73. package/dist/{index-Ciu5Xlml.d.ts → index-D5IfUIDh.d.ts} +6 -5
  74. package/dist/{index-K-3WM2Hp.d.ts → index-DFmOpBGC.d.ts} +13 -13
  75. package/dist/{index-D4v7sncu.d.ts → index-RlLXd8dL.d.ts} +13 -13
  76. package/dist/index.d.ts +17 -17
  77. package/dist/index.js +23 -14
  78. package/dist/{invalidate-DbxuL2jL.js → invalidate-CgxmRamI.js} +7 -1
  79. package/dist/jobs/index.d.ts +33 -26
  80. package/dist/jobs/index.js +44 -22
  81. package/dist/{json-schema-BpYqkCKf.js → json-schema-DP6V7cbr.js} +8 -3
  82. package/dist/lint/index.js +1 -1
  83. package/dist/list/index.d.ts +2 -2
  84. package/dist/list/index.js +131 -96
  85. package/dist/{live-DJyZMD6w.d.ts → live-BHakSWWo.d.ts} +26 -16
  86. package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
  87. package/dist/lookup-BaP5bI27.js +18 -0
  88. package/dist/mcp/index.d.ts +34 -27
  89. package/dist/mcp/index.js +59 -25
  90. package/dist/{mfa-TVia554c.d.ts → mfa-C7MNQ1Ob.d.ts} +1 -1
  91. package/dist/{mfa-CpLfJSde.js → mfa-byfjruR9.js} +190 -46
  92. package/dist/next/image/index.js +6 -3
  93. package/dist/next/index.d.ts +64 -48
  94. package/dist/next/index.js +63 -50
  95. package/dist/openapi/index.d.ts +1 -1
  96. package/dist/openapi/index.js +61 -38
  97. package/dist/orpc/index.d.ts +18 -21
  98. package/dist/orpc/index.js +12 -12
  99. package/dist/otel/index.d.ts +5 -5
  100. package/dist/otel/index.js +84 -63
  101. package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-C4KFzLc9.js} +12 -7
  102. package/dist/permdock-sql-DImJULY-.d.ts +17 -0
  103. package/dist/{plugin-C4TR9J0Z.d.ts → plugin-bNhvJwRh.d.ts} +5 -4
  104. package/dist/plugins/actor/index.d.ts +1 -1
  105. package/dist/plugins/actor/index.js +1 -1
  106. package/dist/plugins/rules/index.d.ts +2 -2
  107. package/dist/plugins/rules/index.js +46 -16
  108. package/dist/plugins/soft-delete/index.d.ts +3 -3
  109. package/dist/plugins/soft-delete/index.js +4 -4
  110. package/dist/plugins/tenant/index.d.ts +3 -3
  111. package/dist/plugins/tenant/index.js +10 -4
  112. package/dist/plugins/timestamps/index.d.ts +1 -1
  113. package/dist/plugins/timestamps/index.js +2 -2
  114. package/dist/plugins/validation/index.d.ts +2 -2
  115. package/dist/plugins/validation/index.js +3 -3
  116. package/dist/pool-DFwEQwmN.d.ts +78 -0
  117. package/dist/postgres/index.d.ts +10 -5
  118. package/dist/postgres/index.js +37 -16
  119. package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-Bc-0Xw62.d.ts} +1 -1
  120. package/dist/{problem-BTkTtRV9.js → problem-BihjPR0t.js} +11 -5
  121. package/dist/{problem-DlgB0lYl.d.ts → problem-U8UEKccv.d.ts} +6 -4
  122. package/dist/query/index.d.ts +2 -2
  123. package/dist/query/index.js +2 -2
  124. package/dist/{query-ChvDbsDE.js → query-BMMSWbI7.js} +19 -19
  125. package/dist/react/index.d.ts +7 -7
  126. package/dist/react/index.js +2 -2
  127. package/dist/react/server.d.ts +6 -6
  128. package/dist/react/server.js +3 -3
  129. package/dist/react/session.d.ts +21 -2
  130. package/dist/react/session.js +19 -1
  131. package/dist/{react-C83BdBGt.js → react-CQHMaESR.js} +59 -55
  132. package/dist/{read-set-4lI3W_gZ.js → read-set-FWK8qQ58.js} +51 -16
  133. package/dist/realtime/index.d.ts +4 -3
  134. package/dist/realtime/index.js +19 -17
  135. package/dist/{index-CG69s15v.d.ts → refresh-BwYkyNOQ.d.ts} +7 -3
  136. package/dist/{resolve-CjHILk2w.d.ts → resolve-BAqQcwMW.d.ts} +17 -11
  137. package/dist/{resource-CgZa3YG_.d.ts → resource-BJcaIfxi.d.ts} +17 -8
  138. package/dist/{resource-BHEWmQJK.js → resource-My_y-Syh.js} +43 -21
  139. package/dist/{respond-Dne1ARSa.d.ts → respond-DgIbdrt8.d.ts} +39 -14
  140. package/dist/{result-DWXatkd6.js → result-Bj6yt33D.js} +2 -2
  141. package/dist/{result-CTkCZ6JA.d.ts → result-CqEsbgYs.d.ts} +16 -11
  142. package/dist/server/index.d.ts +38 -13
  143. package/dist/server/index.js +43 -14
  144. package/dist/{respond-DMcbQwfN.js → server-BA75B0mT.js} +151 -96
  145. package/dist/{shared-_6-uPL7E.js → shared-DnoCdMDr.js} +4 -3
  146. package/dist/{simplify-bwJpLnaS.js → simplify-Cqvfr9dj.js} +76 -39
  147. package/dist/sql/index.d.ts +139 -0
  148. package/dist/sql/index.js +1983 -0
  149. package/dist/{sql-DTjA1LPj.js → sql-B34HU2DI.js} +74 -17
  150. package/dist/ssr/index.d.ts +4 -4
  151. package/dist/ssr/index.js +2 -2
  152. package/dist/{standard-FUi3Z3-7.js → standard-BRyBGTtp.js} +2 -2
  153. package/dist/{standard-CyhRzctb.d.ts → standard-BsaCYQJc.d.ts} +1 -1
  154. package/dist/{stats-C5W-rBfR.js → stats-C_YxA2r1.js} +40 -14
  155. package/dist/storage/index.d.ts +4 -3
  156. package/dist/storage/index.js +548 -1
  157. package/dist/{tables-rZxRxNPW.js → tables-Cb-3_VWc.js} +19 -5
  158. package/dist/temporal-BwshQk0W.js +27 -0
  159. package/dist/temporal-required-CBNHT6ni.js +19 -0
  160. package/dist/testing/index.d.ts +25 -24
  161. package/dist/testing/index.js +165 -66
  162. package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
  163. package/dist/version-Bmf7_FzM.js +4 -0
  164. package/dist/{view-D1s0wa0T.d.ts → view-B64o81wp.d.ts} +36 -6
  165. package/dist/{view-aOYizTeE.js → view-BrJI2LKp.js} +11 -2
  166. package/dist/webhooks/index.d.ts +19 -17
  167. package/dist/webhooks/index.js +1 -1
  168. package/dist/{webhooks-DMipjhSP.js → webhooks-Bh_Jf_-l.js} +45 -24
  169. package/package.json +50 -22
  170. package/schemas/config-v1.json +31 -1
  171. package/schemas/doctor-report-v1.json +17 -1
  172. package/schemas/snapshot-v2.json +35 -0
  173. package/skills/better-supabase/SKILL.md +77 -18
  174. package/skills/better-supabase/references/plugins.md +21 -22
  175. package/skills/better-supabase/references/troubleshooting.md +38 -18
  176. package/skills/better-supabase-api/SKILL.md +66 -18
  177. package/skills/better-supabase-api/references/adapters.md +64 -41
  178. package/skills/better-supabase-auth/SKILL.md +146 -0
  179. package/skills/better-supabase-auth/references/permdock.md +55 -0
  180. package/skills/better-supabase-testing/SKILL.md +68 -11
  181. package/dist/casing-da0uRTqt.js +0 -14
  182. package/dist/claims-CoTobNC-.js +0 -25
  183. package/dist/cli-DrSgDOQC.js +0 -6646
  184. package/dist/env-BEToab0I.js +0 -204
  185. package/dist/events-BuzTgn2D.js +0 -135
  186. package/dist/pool-R2m_DkXi.d.ts +0 -37
  187. package/dist/seed-CzecODcJ.js +0 -101
  188. package/dist/session-C3LxnQ0e.d.ts +0 -22
  189. package/dist/session-CqEwzVup.js +0 -20
  190. 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 };