better-supabase 0.3.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 (172) hide show
  1. package/README.md +7 -6
  2. package/bin/better-supabase.js +4 -0
  3. package/dist/{base64-CQeB1eSf.js → base64-D2gsioCY.js} +2 -2
  4. package/dist/claims-BAf6c7is.js +48 -0
  5. package/dist/cli/_format-Cax5EsM9.js +101 -0
  6. package/dist/cli/bin.d.ts +1 -0
  7. package/dist/cli/bin.js +48 -0
  8. package/dist/cli/command-CK14fP91.js +502 -0
  9. package/dist/cli/compare-BmIWVEui.js +9 -0
  10. package/dist/cli/config-D9R0o1LH.js +1895 -0
  11. package/dist/cli/config-SSKSTUl2.js +2 -0
  12. package/dist/cli/db-DOBPt660.js +52 -0
  13. package/dist/cli/dist-B1MvLv-M.js +129 -0
  14. package/dist/cli/dist-CFgGknmZ.js +1112 -0
  15. package/dist/cli/dist-Du7VnEUG.js +621 -0
  16. package/dist/cli/doctor-BOym3mbL.js +2382 -0
  17. package/dist/cli/env-BZ0uy8XK.js +108 -0
  18. package/dist/cli/env-jIFUADLY.js +511 -0
  19. package/dist/cli/errors-4v4DTtda.js +56 -0
  20. package/dist/cli/fastest-levenshtein-CFN-lNDv.js +120 -0
  21. package/dist/cli/gen-Ccn_p90L.js +2008 -0
  22. package/dist/cli/gen-D5cLCULx.js +2 -0
  23. package/dist/cli/index.d.ts +493 -0
  24. package/dist/cli/index.js +184 -0
  25. package/dist/cli/init-ClnxRYBF.js +550 -0
  26. package/dist/cli/introspect-DxqfkVIv.js +81 -0
  27. package/dist/cli/io-k41_z-jT.js +24 -0
  28. package/dist/cli/json5-ChRycquj.js +787 -0
  29. package/dist/cli/jsonc-BUniUpOk.js +2 -0
  30. package/dist/cli/jsonc-D5Fu67jw.js +45 -0
  31. package/dist/cli/keys-ByKHnvP9.js +83 -0
  32. package/dist/cli/ohash-D7bG_EOb.js +277 -0
  33. package/dist/cli/openapi-8WHjxiTJ.js +66 -0
  34. package/dist/cli/project-B_GeXyHh.js +70 -0
  35. package/dist/cli/prompts-BNcNfAve.js +1142 -0
  36. package/dist/cli/prompts-BTYQGunc.js +2 -0
  37. package/dist/cli/read-sets-CMa29t9a.js +971 -0
  38. package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
  39. package/dist/cli/run-CP20LKk_.js +347 -0
  40. package/dist/cli/seed-5J6eu_Xg.js +98 -0
  41. package/dist/cli/skills-LJJIhLFR.js +137 -0
  42. package/dist/cli/sql-D4VbqmXi.js +199 -0
  43. package/dist/cli/style-C0NFdJRL.js +29 -0
  44. package/dist/cli/toml-DB-MNnFs.js +424 -0
  45. package/dist/cli/version-5mW_8sY1.js +4 -0
  46. package/dist/cli/yaml-CYCbJ6et.js +2252 -0
  47. package/dist/client/index.d.ts +2 -2
  48. package/dist/client/index.js +13 -13
  49. package/dist/{compiler-2zqGzxVZ.d.ts → compiler-DB3aSFOA.d.ts} +2 -2
  50. package/dist/config/index.js +4 -4
  51. package/dist/{config-Be4GwsqI.js → config-BpxDfnbg.js} +1 -1
  52. package/dist/{config-DOsGYSiT.js → config-CbvFmGD8.js} +1 -1
  53. package/dist/{define-DF341GDj.js → define-Bh0AqTik.js} +160 -79
  54. package/dist/{define-DUbydmJa.d.ts → define-CRS2MRV3.d.ts} +32 -28
  55. package/dist/edge/index.d.ts +8 -12
  56. package/dist/edge/index.js +50 -24
  57. package/dist/{entitlements-DvJXoI02.d.ts → entitlements-Dm-FHpNH.d.ts} +2 -2
  58. package/dist/{errors-Bl3rkOzo.js → errors-L0xK41y_.js} +1 -1
  59. package/dist/events/index.d.ts +1 -1
  60. package/dist/events/index.js +4 -4
  61. package/dist/{events-Do8jXh4D.d.ts → events-B21UOhvP.d.ts} +4 -4
  62. package/dist/{executor-DynmIWhq.d.ts → executor-B5IoUxLE.d.ts} +1 -1
  63. package/dist/{executor-C57jx2pn.js → executor-CVt6dD0B.js} +3 -3
  64. package/dist/{executor-B26lgbHD.d.ts → executor-CZ7ImRiD.d.ts} +2 -2
  65. package/dist/hono/index.d.ts +16 -23
  66. package/dist/hono/index.js +10 -10
  67. package/dist/{index-CTTMS6_1.d.ts → index-528Ugmyp.d.ts} +12 -3
  68. package/dist/{index-CADlNHK-.d.ts → index-BAy4tsAP.d.ts} +5 -5
  69. package/dist/{index-BNsABq7P.d.ts → index-BBdvo-5d.d.ts} +23 -25
  70. package/dist/{index-qriRM9cZ.d.ts → index-BhHEC04r.d.ts} +3 -3
  71. package/dist/{index-GV77NpRP.d.ts → index-D5IfUIDh.d.ts} +3 -3
  72. package/dist/{index-CriFFJ_p.d.ts → index-DFmOpBGC.d.ts} +11 -11
  73. package/dist/{index-UJ-LUxtI.d.ts → index-RlLXd8dL.d.ts} +12 -12
  74. package/dist/index.d.ts +15 -15
  75. package/dist/index.js +13 -13
  76. package/dist/{invalidate-DbxuL2jL.js → invalidate-CgxmRamI.js} +7 -1
  77. package/dist/jobs/index.d.ts +10 -4
  78. package/dist/jobs/index.js +32 -16
  79. package/dist/{json-schema--aOXAGfU.js → json-schema-DP6V7cbr.js} +1 -1
  80. package/dist/list/index.d.ts +1 -1
  81. package/dist/list/index.js +3 -3
  82. package/dist/{live-QE3UPbGm.d.ts → live-BHakSWWo.d.ts} +12 -12
  83. package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
  84. package/dist/lookup-BaP5bI27.js +18 -0
  85. package/dist/mcp/index.d.ts +18 -18
  86. package/dist/mcp/index.js +23 -18
  87. package/dist/{mfa-x3V3vGh-.d.ts → mfa-C7MNQ1Ob.d.ts} +1 -1
  88. package/dist/{mfa-BxoR1RkN.js → mfa-byfjruR9.js} +118 -29
  89. package/dist/next/image/index.js +6 -3
  90. package/dist/next/index.d.ts +38 -35
  91. package/dist/next/index.js +41 -33
  92. package/dist/openapi/index.d.ts +1 -1
  93. package/dist/openapi/index.js +6 -6
  94. package/dist/orpc/index.d.ts +17 -20
  95. package/dist/orpc/index.js +11 -11
  96. package/dist/otel/index.d.ts +5 -5
  97. package/dist/otel/index.js +81 -62
  98. package/dist/{permdock-sql-Bta_G0v-.js → permdock-sql-C4KFzLc9.js} +1 -1
  99. package/dist/{plugin-DVRB8qNE.d.ts → plugin-bNhvJwRh.d.ts} +2 -2
  100. package/dist/plugins/actor/index.d.ts +1 -1
  101. package/dist/plugins/actor/index.js +1 -1
  102. package/dist/plugins/rules/index.d.ts +2 -2
  103. package/dist/plugins/rules/index.js +42 -12
  104. package/dist/plugins/soft-delete/index.d.ts +2 -2
  105. package/dist/plugins/soft-delete/index.js +2 -2
  106. package/dist/plugins/tenant/index.d.ts +2 -2
  107. package/dist/plugins/tenant/index.js +10 -4
  108. package/dist/plugins/timestamps/index.d.ts +1 -1
  109. package/dist/plugins/timestamps/index.js +1 -1
  110. package/dist/plugins/validation/index.d.ts +2 -2
  111. package/dist/plugins/validation/index.js +3 -3
  112. package/dist/{pool-B9qsLyFR.d.ts → pool-DFwEQwmN.d.ts} +11 -4
  113. package/dist/postgres/index.d.ts +5 -5
  114. package/dist/postgres/index.js +3 -2
  115. package/dist/{postgrest-DmBlevh-.d.ts → postgrest-Bc-0Xw62.d.ts} +1 -1
  116. package/dist/{problem-CGt1ADix.js → problem-BihjPR0t.js} +1 -1
  117. package/dist/{problem-Z2RTQjZD.d.ts → problem-U8UEKccv.d.ts} +1 -1
  118. package/dist/query/index.d.ts +2 -2
  119. package/dist/query/index.js +2 -2
  120. package/dist/{query-BdKLTPlj.js → query-BMMSWbI7.js} +18 -18
  121. package/dist/react/index.d.ts +6 -6
  122. package/dist/react/index.js +1 -1
  123. package/dist/react/server.d.ts +5 -5
  124. package/dist/react/server.js +3 -3
  125. package/dist/react/session.d.ts +4 -4
  126. package/dist/react/session.js +2 -2
  127. package/dist/{react-DNBYNazu.js → react-CQHMaESR.js} +39 -39
  128. package/dist/{read-set-D0qBcboM.js → read-set-FWK8qQ58.js} +50 -15
  129. package/dist/realtime/index.d.ts +1 -1
  130. package/dist/realtime/index.js +13 -12
  131. package/dist/{index-kpgopLNv.d.ts → refresh-BwYkyNOQ.d.ts} +6 -3
  132. package/dist/{resolve-BRciX2jK.d.ts → resolve-BAqQcwMW.d.ts} +15 -10
  133. package/dist/{resource-CwVgiI5q.d.ts → resource-BJcaIfxi.d.ts} +5 -5
  134. package/dist/{resource-D30rp0GN.js → resource-My_y-Syh.js} +6 -6
  135. package/dist/{respond-DAkPIdTH.d.ts → respond-DgIbdrt8.d.ts} +31 -12
  136. package/dist/{result-DWXatkd6.js → result-Bj6yt33D.js} +2 -2
  137. package/dist/{result-c2OYgCV2.d.ts → result-CqEsbgYs.d.ts} +3 -3
  138. package/dist/server/index.d.ts +14 -14
  139. package/dist/server/index.js +12 -12
  140. package/dist/{respond-C44EZAJo.js → server-BA75B0mT.js} +139 -100
  141. package/dist/{shared-_6-uPL7E.js → shared-DnoCdMDr.js} +4 -3
  142. package/dist/{simplify-LakqK1vH.js → simplify-Cqvfr9dj.js} +67 -24
  143. package/dist/sql/index.d.ts +1 -1
  144. package/dist/sql/index.js +7 -7
  145. package/dist/{sql-BIgk12ew.js → sql-B34HU2DI.js} +3 -2
  146. package/dist/ssr/index.d.ts +4 -4
  147. package/dist/ssr/index.js +2 -2
  148. package/dist/{standard-FUi3Z3-7.js → standard-BRyBGTtp.js} +2 -2
  149. package/dist/{standard-eudBiRk1.d.ts → standard-BsaCYQJc.d.ts} +1 -1
  150. package/dist/{stats-D78UQ8Yu.js → stats-C_YxA2r1.js} +33 -8
  151. package/dist/storage/index.d.ts +2 -2
  152. package/dist/storage/index.js +26 -8
  153. package/dist/{tables-Dhha3BXM.js → tables-Cb-3_VWc.js} +14 -0
  154. package/dist/{temporal-required-CMxeSVPo.js → temporal-required-CBNHT6ni.js} +1 -1
  155. package/dist/testing/index.d.ts +20 -21
  156. package/dist/testing/index.js +45 -45
  157. package/dist/{version-BfpG2gks.js → version-Bmf7_FzM.js} +1 -1
  158. package/dist/{view-3Po_PVlr.d.ts → view-B64o81wp.d.ts} +5 -5
  159. package/dist/{view-wZ-9qIUz.js → view-BrJI2LKp.js} +1 -1
  160. package/dist/webhooks/index.d.ts +3 -3
  161. package/dist/webhooks/index.js +1 -1
  162. package/dist/{webhooks-CAIFQSTM.js → webhooks-Bh_Jf_-l.js} +37 -18
  163. package/package.json +36 -4
  164. package/skills/better-supabase/SKILL.md +57 -10
  165. package/skills/better-supabase/references/plugins.md +7 -11
  166. package/skills/better-supabase/references/troubleshooting.md +24 -4
  167. package/skills/better-supabase-api/SKILL.md +66 -18
  168. package/skills/better-supabase-api/references/adapters.md +44 -26
  169. package/skills/better-supabase-auth/SKILL.md +146 -0
  170. package/skills/better-supabase-auth/references/permdock.md +55 -0
  171. package/skills/better-supabase-testing/SKILL.md +58 -4
  172. package/dist/claims-CoTobNC-.js +0 -25
@@ -0,0 +1,24 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ export { __toESM as n, __commonJSMin as t };
@@ -0,0 +1,347 @@
1
+ import { n as __toESM } from "./rolldown-runtime-BPOCksWG.js";
2
+ import { c as parseArgs$2, i as joinRepeated, l as renderUsage, n as cliContext, o as listArgs, s as defineCommand, t as GLOBAL_ARGS, u as runCommand } from "./command-CK14fP91.js";
3
+ import { n as CliError, r as toCliError } from "./errors-4v4DTtda.js";
4
+ import { n as highlight, r as painter } from "./style-C0NFdJRL.js";
5
+ import { t as VERSION } from "./version-5mW_8sY1.js";
6
+ import { stripVTControlCharacters } from "node:util";
7
+ import { resolve } from "node:path";
8
+ //#region src/cli/legacy.ts
9
+ const ARRAY_FLAGS = /* @__PURE__ */ new Set([
10
+ "schema",
11
+ "only",
12
+ "ignore",
13
+ "agent",
14
+ "kit",
15
+ "with",
16
+ "explain"
17
+ ]);
18
+ const BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
19
+ "check",
20
+ "watch",
21
+ "json",
22
+ "strict",
23
+ "help",
24
+ "version",
25
+ "force",
26
+ "dry-run",
27
+ "no-color",
28
+ "yes",
29
+ "local",
30
+ "rotate",
31
+ "apply",
32
+ "print",
33
+ "global",
34
+ "stats",
35
+ "fix-grants"
36
+ ]);
37
+ function parseArgs$1(argv) {
38
+ const flags = {};
39
+ const positionals = [];
40
+ for (let index = 0; index < argv.length; index += 1) {
41
+ const token = argv[index];
42
+ if (token === void 0) continue;
43
+ if (token === "--") {
44
+ positionals.push(...argv.slice(index + 1));
45
+ break;
46
+ }
47
+ if (token === "-h") {
48
+ flags["help"] = true;
49
+ continue;
50
+ }
51
+ if (token.startsWith("--")) {
52
+ const body = token.slice(2);
53
+ const eq = body.indexOf("=");
54
+ if (eq !== -1) {
55
+ setFlag(flags, body.slice(0, eq), body.slice(eq + 1));
56
+ continue;
57
+ }
58
+ const next = argv[index + 1];
59
+ if (!BOOLEAN_FLAGS.has(body) && next !== void 0 && !next.startsWith("-")) {
60
+ setFlag(flags, body, next);
61
+ index += 1;
62
+ continue;
63
+ }
64
+ flags[body] = true;
65
+ continue;
66
+ }
67
+ positionals.push(token);
68
+ }
69
+ return {
70
+ command: positionals[0],
71
+ rest: positionals.slice(1),
72
+ flags
73
+ };
74
+ }
75
+ function setFlag(flags, name, value) {
76
+ if (ARRAY_FLAGS.has(name)) {
77
+ const current = flags[name];
78
+ const pieces = value.split(",").map((item) => item.trim()).filter(Boolean);
79
+ flags[name] = typeof current === "object" ? [...current, ...pieces] : pieces;
80
+ return;
81
+ }
82
+ flags[name] = value;
83
+ }
84
+ /**
85
+ * Wraps a `(context) => CommandResult` command as a citty command. Its flags
86
+ * are parsed the way 0.2 parsed them, because it declares no citty args.
87
+ */
88
+ function legacyCommand(name, command, help) {
89
+ return defineCommand({
90
+ meta: {
91
+ name,
92
+ description: help ?? ""
93
+ },
94
+ run: ({ rawArgs, data }) => {
95
+ const parsed = parseArgs$1([name, ...rawArgs]);
96
+ const context = cliContext(data);
97
+ return command({
98
+ ...context,
99
+ env: { ...context.env },
100
+ args: parsed
101
+ });
102
+ }
103
+ });
104
+ }
105
+ //#endregion
106
+ //#region src/cli/output.ts
107
+ const document = (value) => JSON.stringify(value, null, 2);
108
+ /**
109
+ * A command's result. Under `--json`, stdout gets the command's `data`, or
110
+ * `{ "message": output }` when it has none, or Problem Details when it failed
111
+ * without data; the text output moves to stderr as a diagnostic.
112
+ */
113
+ function renderResult(result, options) {
114
+ if (!options.json) return {
115
+ ...result.output ? { stdout: highlight(result.output, options.paint) } : {},
116
+ ...result.error ? { stderr: options.paint("red", result.error) } : {}
117
+ };
118
+ if (result.data === void 0 && result.error) return {
119
+ stdout: document(new CliError("failed", result.error, { exitCode: result.code }).problem),
120
+ ...result.output ? { stderr: result.output } : {}
121
+ };
122
+ const diagnostics = [...result.data !== void 0 && result.output ? [result.output] : [], ...result.error ? [result.error] : []];
123
+ return {
124
+ stdout: document(result.data ?? { message: result.output ?? "" }),
125
+ ...diagnostics.length > 0 ? { stderr: diagnostics.join("\n") } : {}
126
+ };
127
+ }
128
+ /** An error that stopped the run, with the usage text for usage errors. */
129
+ function renderError(error, options) {
130
+ if (options.json) return { stdout: document(error.problem) };
131
+ return { stderr: options.usage ? `${error.message}\n\n${options.usage}` : error.message };
132
+ }
133
+ //#endregion
134
+ //#region src/cli/run.ts
135
+ const COMMANDS = /* @__PURE__ */ new Map([
136
+ ["init", {
137
+ load: () => import("./init-ClnxRYBF.js").then((m) => m.initCommand),
138
+ description: "Writes better-supabase.config.ts, src/lib/supabase/index.ts and glue for the frameworks in package.json"
139
+ }],
140
+ ["add", {
141
+ load: () => import("./init-ClnxRYBF.js").then((m) => m.addCommand),
142
+ description: "Adds glue for an integration to an existing project"
143
+ }],
144
+ ["env", {
145
+ load: () => import("./env-jIFUADLY.js").then((m) => m.envCommand),
146
+ description: "Writes the local stack's URL and keys from `supabase status` to an env file, keeping its other lines"
147
+ }],
148
+ ["keys", {
149
+ load: () => import("./keys-ByKHnvP9.js").then((m) => m.keysCommand),
150
+ description: "Creates an ES256 signing key for the local stack, so local tokens verify through JWKS like hosted ones"
151
+ }],
152
+ ["skills", {
153
+ load: () => import("./skills-LJJIhLFR.js").then((m) => m.skillsCommand),
154
+ description: "Installs the Agent Skills that ship with this version of better-supabase"
155
+ }],
156
+ ["gen", {
157
+ load: () => import("./gen-D5cLCULx.js").then((m) => m.genCommand),
158
+ description: "Writes database.types.ts, generated.ts and its metadata module from the database"
159
+ }],
160
+ ["introspect", {
161
+ load: () => import("./introspect-DxqfkVIv.js").then((m) => m.introspectCommand),
162
+ description: "Saves the database schema as a snapshot for offline gen"
163
+ }],
164
+ ["openapi", {
165
+ load: () => import("./openapi-8WHjxiTJ.js").then((m) => m.openapiCommand),
166
+ description: "Writes the document your createOpenApi() module exports, so CI can check it for drift"
167
+ }],
168
+ ["seed", {
169
+ load: () => import("./seed-5J6eu_Xg.js").then((m) => m.seedCommand),
170
+ description: "Renders the fixtures from defineSeed() (better-supabase/testing) to SQL"
171
+ }],
172
+ ["doctor", {
173
+ load: () => import("./doctor-BOym3mbL.js").then((m) => m.doctorCommand),
174
+ description: "Checks RLS, indexes, drift, auth config and env files; exits 1 on errors, or on warnings with --strict"
175
+ }],
176
+ ["sql", {
177
+ load: () => import("./sql-D4VbqmXi.js").then((m) => m.sqlCommand),
178
+ description: "Lists, adds, syncs and prints SQL kit modules"
179
+ }]
180
+ ]);
181
+ function registerCommand(name, command, help) {
182
+ const def = typeof command === "function" ? legacyCommand(name, command, help) : command;
183
+ COMMANDS.set(name, {
184
+ load: () => Promise.resolve(def),
185
+ command: def
186
+ });
187
+ }
188
+ const ROOT = defineCommand({
189
+ meta: {
190
+ name: "better-supabase",
191
+ version: VERSION,
192
+ description: "Typed Supabase: codegen, doctor, the SQL kit and project setup"
193
+ },
194
+ args: GLOBAL_ARGS,
195
+ subCommands: () => Object.fromEntries([...COMMANDS].map(([name, entry]) => [name, "command" in entry ? entry.command : defineCommand({ meta: {
196
+ name,
197
+ description: entry.description
198
+ } })]))
199
+ });
200
+ /** The usage text for the CLI, or for one command; plain unless `color` is set. */
201
+ async function help(command, color = false) {
202
+ const load = command === void 0 ? void 0 : COMMANDS.get(command)?.load;
203
+ const text = load ? await renderUsage(await load(), ROOT) : await renderUsage(ROOT);
204
+ return color ? text : stripVTControlCharacters(text);
205
+ }
206
+ /** The index of the command name: the first token that is not an option or an option's value. */
207
+ function commandIndex(argv) {
208
+ for (let index = 0; index < argv.length; index += 1) {
209
+ const token = argv[index];
210
+ if (token === "--") return -1;
211
+ if (!token.startsWith("-")) return index;
212
+ if (token === "--cwd" || token === "--config") index += 1;
213
+ }
214
+ return -1;
215
+ }
216
+ function isCommandResult(value) {
217
+ return typeof value === "object" && value !== null && "code" in value && typeof value.code === "number";
218
+ }
219
+ /** The names `run()` dispatches, registered commands included. */
220
+ function commandNames() {
221
+ return [...COMMANDS.keys()];
222
+ }
223
+ /** The registered command closest to a mistyped one, if it is close enough to be a typo. */
224
+ async function suggestCommand(name) {
225
+ const names = [...COMMANDS.keys()];
226
+ if (names.length === 0) return void 0;
227
+ const { closest, distance } = await import("./fastest-levenshtein-CFN-lNDv.js").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
228
+ const candidate = closest(name, names);
229
+ return distance(name, candidate) <= Math.max(2, Math.floor(name.length / 3)) ? candidate : void 0;
230
+ }
231
+ const SHOWS_USAGE = /* @__PURE__ */ new Set(["usage", "unknown_command"]);
232
+ function withoutPrompts(io) {
233
+ const { prompts: _prompts, ...rest } = io;
234
+ return rest;
235
+ }
236
+ /** Runs the CLI. Never exits the process; returns the exit code and output. */
237
+ async function run(argv, options = {}) {
238
+ const stdout = [];
239
+ const stderr = [];
240
+ const io = options.io ?? {
241
+ stdout: (text) => {
242
+ stdout.push(text);
243
+ },
244
+ stderr: (text) => {
245
+ stderr.push(text);
246
+ }
247
+ };
248
+ const out = (text) => {
249
+ const line = text.endsWith("\n") ? text : `${text}\n`;
250
+ if (options.io) stdout.push(line);
251
+ io.stdout(line);
252
+ };
253
+ const fail = (text) => {
254
+ const line = text.endsWith("\n") ? text : `${text}\n`;
255
+ if (options.io) stderr.push(line);
256
+ io.stderr(line);
257
+ };
258
+ const paint = painter(io.color);
259
+ const usage = (command) => help(command, io.color === true);
260
+ const finish = (code) => ({
261
+ code,
262
+ stdout: stdout.join(""),
263
+ stderr: stderr.join("")
264
+ });
265
+ const index = commandIndex(argv);
266
+ const name = index === -1 ? void 0 : argv[index];
267
+ const rest = index === -1 ? [...argv] : argv.toSpliced(index, 1);
268
+ const flags = new Set(rest.slice(0, rest.includes("--") ? rest.indexOf("--") : void 0));
269
+ const wantsHelp = flags.has("--help") || flags.has("-h");
270
+ const json = flags.has("--json");
271
+ const report = (rendered) => {
272
+ if (rendered.stdout) out(rendered.stdout);
273
+ if (rendered.stderr) fail(rendered.stderr);
274
+ };
275
+ const reportError = async (cause) => {
276
+ const error = toCliError(cause);
277
+ const shown = error.code === "usage" ? new CliError("usage", stripVTControlCharacters(error.message)) : error;
278
+ report(renderError(shown, {
279
+ json,
280
+ paint,
281
+ ...SHOWS_USAGE.has(error.code) ? { usage: await usage(error.code === "usage" ? name : void 0) } : {}
282
+ }));
283
+ return finish(error.exitCode);
284
+ };
285
+ if (flags.has("--version") || name === "version") {
286
+ out(json ? JSON.stringify({ version: VERSION }) : VERSION);
287
+ return finish(0);
288
+ }
289
+ if (name === void 0) {
290
+ (wantsHelp ? out : fail)(await usage());
291
+ return finish(wantsHelp ? 0 : 2);
292
+ }
293
+ if (name === "help") {
294
+ out(await usage(rest.find((token) => !token.startsWith("-"))));
295
+ return finish(0);
296
+ }
297
+ const load = COMMANDS.get(name)?.load;
298
+ if (!load) {
299
+ const suggestion = await suggestCommand(name);
300
+ return reportError(new CliError("unknown_command", `Unknown command "${name}".${suggestion ? ` Did you mean "${suggestion}"?` : ""}`, suggestion ? { suggestion } : {}));
301
+ }
302
+ if (wantsHelp) {
303
+ out(await usage(name));
304
+ return finish(0);
305
+ }
306
+ let context;
307
+ let command;
308
+ try {
309
+ const [loaded, { loadConfig }, { parseEnv }] = await Promise.all([
310
+ load(),
311
+ import("./config-SSKSTUl2.js"),
312
+ import("./env-BZ0uy8XK.js")
313
+ ]);
314
+ command = loaded;
315
+ const globals = parseArgs$2(rest, GLOBAL_ARGS);
316
+ const cwd = resolve(options.cwd ?? ".", globals.cwd ?? ".");
317
+ const env = parseEnv(options.env ?? {});
318
+ context = {
319
+ cwd,
320
+ config: await loadConfig(cwd, globals.config).catch((cause) => {
321
+ throw cause instanceof CliError ? cause : new CliError("config_invalid", toCliError(cause).message, { cause });
322
+ }),
323
+ io: globals.json !== true && globals.yes !== true && env.CI === void 0 ? io : withoutPrompts(io),
324
+ env,
325
+ json: globals.json === true,
326
+ signal: options.signal
327
+ };
328
+ } catch (cause) {
329
+ return reportError(cause);
330
+ }
331
+ try {
332
+ const { result } = await runCommand(command, {
333
+ rawArgs: joinRepeated(rest, listArgs(command)),
334
+ data: context
335
+ });
336
+ if (!isCommandResult(result)) return finish(0);
337
+ report(renderResult(result, {
338
+ json,
339
+ paint
340
+ }));
341
+ return finish(result.code);
342
+ } catch (cause) {
343
+ return reportError(cause);
344
+ }
345
+ }
346
+ //#endregion
347
+ export { run as i, help as n, registerCommand as r, commandNames as t };
@@ -0,0 +1,98 @@
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 importExport, s as stdinDatabaseUrl, t as databaseUrl } from "./config-D9R0o1LH.js";
4
+ import { n as withSpinner } from "./prompts-BNcNfAve.js";
5
+ import { t as connect } from "./db-DOBPt660.js";
6
+ import { resolve } from "node:path";
7
+ import { existsSync } from "node:fs";
8
+ import { readFile } from "node:fs/promises";
9
+ import { isSeed } from "better-supabase/testing";
10
+ //#region src/cli/commands/seed.ts
11
+ const ARGS = {
12
+ check: {
13
+ type: "boolean",
14
+ description: "Fail when the SQL file is out of date"
15
+ },
16
+ apply: {
17
+ type: "boolean",
18
+ description: "Also insert the rows into the database ($DATABASE_URL, --db-url-stdin, or the local stack)"
19
+ },
20
+ entry: {
21
+ type: "string",
22
+ description: "Defaults to seed.entry (supabase/seed.ts)",
23
+ valueHint: "file"
24
+ },
25
+ out: {
26
+ type: "string",
27
+ description: "Defaults to seed.output (supabase/seeds/000_better_supabase.sql)",
28
+ valueHint: "file"
29
+ },
30
+ "db-url-stdin": {
31
+ type: "boolean",
32
+ description: "Read the connection string from stdin instead of $DATABASE_URL or the config"
33
+ }
34
+ };
35
+ const HEADER = "-- Generated by `better-supabase seed`";
36
+ async function runSeed(config, args, env, open = connect, dbUrl) {
37
+ const entry = args.entry ?? config.seed.entry;
38
+ const out = args.out ?? config.seed.output;
39
+ const seed = await importExport(resolve(config.root, entry), "seed");
40
+ if (!isSeed(seed)) return {
41
+ code: 1,
42
+ error: `${display(config.root, entry)} must export defineSeed(...) as \`seed\` or default.`
43
+ };
44
+ const statements = seed.statements();
45
+ const contents = `${HEADER} from ${display(config.root, entry)}. Do not edit.\n\n${statements.join("\n\n")}\n`;
46
+ const path = resolve(config.root, out);
47
+ const current = existsSync(path) ? await readFile(path, "utf8") : void 0;
48
+ if (args.check === true) return current === contents ? {
49
+ code: 0,
50
+ output: `${display(config.root, out)} is up to date.`
51
+ } : {
52
+ code: 1,
53
+ error: `${display(config.root, out)} is out of date. Run \`better-supabase seed\`.`
54
+ };
55
+ if (current !== void 0 && !current.startsWith(HEADER)) return {
56
+ code: 1,
57
+ error: `${display(config.root, out)} was not written by better-supabase; pass --out to write elsewhere.`
58
+ };
59
+ const lines = [`${await writeIfChanged(path, contents) ? "Wrote" : "Unchanged"} ${display(config.root, out)} (${statements.length} table${statements.length === 1 ? "" : "s"})`];
60
+ if (args.apply === true) {
61
+ const { client, close } = await open(await databaseUrl(config, env, dbUrl));
62
+ try {
63
+ await client.query("begin");
64
+ for (const text of statements) await client.query(text);
65
+ await client.query("commit");
66
+ } catch (error) {
67
+ await client.query("rollback");
68
+ throw error;
69
+ } finally {
70
+ await close();
71
+ }
72
+ lines.push("Inserted the fixtures (existing rows were kept).");
73
+ }
74
+ const toml = resolve(config.root, "supabase/config.toml");
75
+ const seedPath = out.startsWith("supabase/") ? `./${out.slice(9)}` : out;
76
+ if (existsSync(toml)) {
77
+ const text = await readFile(toml, "utf8");
78
+ const folder = seedPath.replace(/[^/]+$/, "");
79
+ if (!text.includes(seedPath) && !text.includes(`${folder}*`)) lines.push("", "Add it to supabase/config.toml so `supabase db reset` runs it:", " [db.seed]", ` sql_paths = ["./seed.sql", "${seedPath}"]`);
80
+ }
81
+ return {
82
+ code: 0,
83
+ output: lines.join("\n")
84
+ };
85
+ }
86
+ const seedCommand = defineCliCommand({
87
+ meta: {
88
+ name: "seed",
89
+ description: "Renders the fixtures from defineSeed() (better-supabase/testing) to SQL"
90
+ },
91
+ args: ARGS,
92
+ run: async (args, { config, env, io }) => {
93
+ const dbUrl = await stdinDatabaseUrl(args["db-url-stdin"], io);
94
+ return withSpinner(args.apply === true ? io.prompts : void 0, "Inserting the seed rows", () => runSeed(config, args, env, connect, dbUrl));
95
+ }
96
+ });
97
+ //#endregion
98
+ export { seedCommand };
@@ -0,0 +1,137 @@
1
+ import { a as list, r as defineCliCommand } from "./command-CK14fP91.js";
2
+ import { r as writeIfChanged, t as display } from "./io-k41_z-jT.js";
3
+ import { t as byCodePoint } from "./compare-BmIWVEui.js";
4
+ import { dirname, join, resolve } from "node:path";
5
+ import { existsSync } from "node:fs";
6
+ import { readFile, readdir } from "node:fs/promises";
7
+ import { fileURLToPath } from "node:url";
8
+ import { homedir } from "node:os";
9
+ //#region src/cli/commands/skills.ts
10
+ const ARGS = {
11
+ action: {
12
+ type: "positional",
13
+ required: false,
14
+ description: "list or install"
15
+ },
16
+ agent: {
17
+ type: "string",
18
+ description: "cursor (.cursor/skills), claude (.claude/skills) or agents (.agents/skills). Defaults to the agent folders the project has, else agents",
19
+ valueHint: "names"
20
+ },
21
+ global: {
22
+ type: "boolean",
23
+ description: "Install into your home directory instead of the project"
24
+ },
25
+ check: {
26
+ type: "boolean",
27
+ description: "Fail when installed skills differ from this version"
28
+ },
29
+ from: {
30
+ type: "string",
31
+ description: "Read skills from this folder instead of the package",
32
+ valueHint: "dir"
33
+ }
34
+ };
35
+ const AGENT_DIRS = {
36
+ cursor: ".cursor/skills",
37
+ claude: ".claude/skills",
38
+ agents: ".agents/skills"
39
+ };
40
+ const isAgent = (name) => name in AGENT_DIRS;
41
+ /** The `skills/` folder of the `better-supabase` package this CLI depends on. */
42
+ function skillsRoot() {
43
+ const root = join(dirname(fileURLToPath(import.meta.resolve("better-supabase/package.json"))), "skills");
44
+ if (!existsSync(root)) throw new Error("Could not find the better-supabase skills folder.");
45
+ return root;
46
+ }
47
+ async function readTree(root, prefix = "") {
48
+ const files = [];
49
+ const entries = await readdir(join(root, prefix), { withFileTypes: true });
50
+ for (const entry of entries.sort((a, b) => byCodePoint(a.name, b.name))) {
51
+ const path = prefix ? `${prefix}/${entry.name}` : entry.name;
52
+ if (entry.isDirectory()) files.push(...await readTree(root, path));
53
+ else if (entry.isFile()) files.push({
54
+ path,
55
+ contents: await readFile(join(root, path), "utf8")
56
+ });
57
+ }
58
+ return files;
59
+ }
60
+ async function loadSkills(root = skillsRoot()) {
61
+ const skills = [];
62
+ for (const entry of (await readdir(root, { withFileTypes: true })).filter((item) => item.isDirectory())) {
63
+ const folder = join(root, entry.name);
64
+ if (!existsSync(join(folder, "SKILL.md"))) continue;
65
+ const tree = await readTree(folder);
66
+ const main = tree.find((file) => file.path === "SKILL.md");
67
+ const files = [main, ...tree.filter((file) => file !== main)];
68
+ const description = /^description:\s*(.+)$/m.exec(main.contents)?.[1] ?? "";
69
+ skills.push({
70
+ name: entry.name,
71
+ description,
72
+ contents: main.contents,
73
+ files
74
+ });
75
+ }
76
+ return skills.sort((a, b) => byCodePoint(a.name, b.name));
77
+ }
78
+ async function runSkills(config, args, env) {
79
+ const [action] = args._;
80
+ const skills = await loadSkills(args.from ?? skillsRoot());
81
+ if (action === "list") return {
82
+ code: 0,
83
+ output: skills.map((skill) => `${skill.name}\n ${skill.description}`).join("\n")
84
+ };
85
+ if (action !== "install") return {
86
+ code: 2,
87
+ error: `${action ? `Unknown skills action "${action}"` : "Name an action"}. Use \`skills list\` or \`skills install\`.`
88
+ };
89
+ const global = args.global === true;
90
+ const base = global ? env.HOME ?? homedir() : config.root;
91
+ const requested = list(args.agent);
92
+ const unknown = requested.filter((name) => !isAgent(name));
93
+ if (unknown.length > 0) return {
94
+ code: 2,
95
+ error: `Unknown agent ${unknown.join(", ")}. Use ${Object.keys(AGENT_DIRS).join(", ")}.`
96
+ };
97
+ const detected = Object.keys(AGENT_DIRS).filter((agent) => existsSync(join(base, AGENT_DIRS[agent].split("/")[0])));
98
+ const agents = requested.length > 0 ? requested.filter(isAgent) : detected.length > 0 ? detected : ["agents"];
99
+ const check = args.check === true;
100
+ const lines = [];
101
+ const stale = [];
102
+ const targets = agents.flatMap((agent) => skills.flatMap((skill) => skill.files.map((file) => ({
103
+ file,
104
+ relativePath: join(AGENT_DIRS[agent], skill.name, file.path)
105
+ }))));
106
+ for (const { file, relativePath } of targets) {
107
+ const path = resolve(base, relativePath);
108
+ const shown = global ? `~/${relativePath}` : display(config.root, relativePath);
109
+ if (check) {
110
+ if ((existsSync(path) ? await readFile(path, "utf8") : void 0) !== file.contents) stale.push(shown);
111
+ continue;
112
+ }
113
+ lines.push(`${await writeIfChanged(path, file.contents) ? "Wrote" : "Unchanged"} ${shown}`);
114
+ }
115
+ if (check) return stale.length === 0 ? {
116
+ code: 0,
117
+ output: "Skills are up to date."
118
+ } : {
119
+ code: 1,
120
+ error: `Out of date: ${stale.join(", ")}. Run \`better-supabase skills install\`.`
121
+ };
122
+ return {
123
+ code: 0,
124
+ output: lines.join("\n")
125
+ };
126
+ }
127
+ const skillsCommand = defineCliCommand({
128
+ meta: {
129
+ name: "skills",
130
+ description: "Installs the Agent Skills that ship with this version of better-supabase"
131
+ },
132
+ args: ARGS,
133
+ lists: ["agent"],
134
+ run: (args, { config, env }) => runSkills(config, args, env)
135
+ });
136
+ //#endregion
137
+ export { skillsCommand };