better-supabase 0.3.0 → 0.5.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 +9 -6
- package/bin/better-supabase.js +4 -0
- package/dist/{base64-CQeB1eSf.js → base64-D2gsioCY.js} +2 -2
- package/dist/channel-FQW-CnGR.d.ts +70 -0
- package/dist/claims-BAf6c7is.js +48 -0
- package/dist/cli/_format-Cax5EsM9.js +101 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +48 -0
- package/dist/cli/codemod-DqV7612m.js +388 -0
- package/dist/cli/command-CK14fP91.js +502 -0
- package/dist/cli/compare-BmIWVEui.js +9 -0
- package/dist/cli/config-CPVpXP5I.js +1965 -0
- package/dist/cli/config-dtoekM0v.js +2 -0
- package/dist/cli/db-DOBPt660.js +52 -0
- package/dist/cli/diff-SjkO5rNr.js +752 -0
- package/dist/cli/dist-DBPdlPYK.js +1112 -0
- package/dist/cli/dist-DreZ24Sz.js +129 -0
- package/dist/cli/dist-xn4wlboc.js +732 -0
- package/dist/cli/doctor-L7Z8mYTx.js +2863 -0
- package/dist/cli/env-DmKv_G4A.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-BJc9vdyu.js +2 -0
- package/dist/cli/gen-C2osRcr5.js +2204 -0
- package/dist/cli/index.d.ts +493 -0
- package/dist/cli/index.js +184 -0
- package/dist/cli/init-Saf5-R9T.js +550 -0
- package/dist/cli/introspect--H7oGmcd.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-Cp5Fyta-.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-BfMQcKy8.js +289 -0
- package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
- package/dist/cli/run-BKR2W_79.js +351 -0
- package/dist/cli/seed-CUlqWh-8.js +98 -0
- package/dist/cli/skills-LJJIhLFR.js +137 -0
- package/dist/cli/sql-DzPbfngx.js +348 -0
- package/dist/cli/style-C0NFdJRL.js +29 -0
- package/dist/cli/toml-DB-MNnFs.js +424 -0
- package/dist/cli/version-BDJuO0UR.js +4 -0
- package/dist/cli/yaml-CYCbJ6et.js +2252 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +15 -22
- package/dist/clone-BfgmLU90.js +21 -0
- package/dist/{compiler-2zqGzxVZ.d.ts → compiler-BXH_aZ7N.d.ts} +2 -2
- package/dist/config/index.d.ts +4 -4
- package/dist/config/index.js +5 -5
- package/dist/{config-DOsGYSiT.js → config-DreERlKo.js} +1 -1
- package/dist/{config-C1CYcm6o.d.ts → config-T_ejwyd3.d.ts} +176 -11
- package/dist/{define-DUbydmJa.d.ts → define-Bp_BZa5h.d.ts} +37 -29
- package/dist/{define-DF341GDj.js → define-cNKzqwL_.js} +356 -89
- package/dist/edge/index.d.ts +20 -13
- package/dist/edge/index.js +55 -26
- package/dist/{entitlements-DvJXoI02.d.ts → entitlements-DUxU4oHe.d.ts} +2 -2
- package/dist/env/index.d.ts +2 -2
- package/dist/env/index.js +34 -1
- package/dist/{errors-Bl3rkOzo.js → errors-DtwXa6b8.js} +2 -1
- package/dist/events/index.d.ts +3 -2
- package/dist/events/index.js +69 -16
- package/dist/events-aIO7vsIk.d.ts +230 -0
- package/dist/executor-BunPOO-k.d.ts +402 -0
- package/dist/{executor-B26lgbHD.d.ts → executor-Cghdstwu.d.ts} +1 -2
- package/dist/{executor-C57jx2pn.js → executor-XycESQPH.js} +3 -3
- package/dist/hono/index.d.ts +27 -23
- package/dist/hono/index.js +46 -11
- package/dist/impersonation-VfaGc4Q_.js +41 -0
- package/dist/{index-BNsABq7P.d.ts → index-BGdgBPdf.d.ts} +66 -25
- package/dist/{index-qriRM9cZ.d.ts → index-C7f8cOBM.d.ts} +4 -4
- package/dist/{index-Dy6kuF0P.d.ts → index-CLg87OBW.d.ts} +6 -1
- package/dist/{index-GV77NpRP.d.ts → index-DOESKG27.d.ts} +34 -9
- package/dist/{index-CriFFJ_p.d.ts → index-DgILJRXj.d.ts} +43 -17
- package/dist/{index-UJ-LUxtI.d.ts → index-DmXSxbLi.d.ts} +14 -14
- package/dist/{index-Cf-D2jk1.d.ts → index-Dxn2a5cw.d.ts} +2 -2
- package/dist/{index-CTTMS6_1.d.ts → index-SaTsEfGP.d.ts} +86 -9
- package/dist/{index-CADlNHK-.d.ts → index-fag8VJZ2.d.ts} +5 -6
- package/dist/index.d.ts +34 -17
- package/dist/index.js +15 -14
- package/dist/jobs/index.d.ts +147 -95
- package/dist/jobs/index.js +773 -250
- package/dist/{json-schema--aOXAGfU.js → json-schema-m1fiwKgN.js} +23 -2
- package/dist/kit-events-CTFDfSwb.js +60 -0
- package/dist/kit-transport-B82k1djG.d.ts +33 -0
- package/dist/kit-transport-DJlHQUBU.js +55 -0
- package/dist/{config-Be4GwsqI.js → kits-CGLLrNPd.js} +38 -10
- package/dist/list/index.d.ts +1 -1
- package/dist/list/index.js +3 -3
- package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
- package/dist/{live-QE3UPbGm.d.ts → live-D9W2M5aO.d.ts} +16 -15
- package/dist/lookup-BaP5bI27.js +18 -0
- package/dist/mcp/index.d.ts +39 -22
- package/dist/mcp/index.js +39 -25
- package/dist/{mfa-x3V3vGh-.d.ts → mfa-CusDgPaD.d.ts} +5 -1
- package/dist/next/image/index.js +6 -3
- package/dist/next/index.d.ts +60 -36
- package/dist/next/index.js +167 -50
- package/dist/notifications/index.d.ts +162 -0
- package/dist/notifications/index.js +264 -0
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +6 -6
- package/dist/orgs/index.d.ts +132 -0
- package/dist/orgs/index.js +245 -0
- package/dist/orpc/index.d.ts +37 -20
- package/dist/orpc/index.js +24 -11
- package/dist/otel/index.d.ts +24 -5
- package/dist/otel/index.js +124 -64
- package/dist/permdock-sql-C2Inc6Xc.d.ts +29 -0
- package/dist/permdock-sql-DgOfeixi.js +51 -0
- package/dist/plugin-DwARMuQp.js +59 -0
- package/dist/{plugin-DVRB8qNE.d.ts → plugin-o144f322.d.ts} +17 -5
- package/dist/plugins/actor/index.d.ts +5 -2
- package/dist/plugins/actor/index.js +22 -8
- package/dist/plugins/rules/index.d.ts +2 -2
- package/dist/plugins/rules/index.js +52 -17
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +14 -5
- package/dist/plugins/tenant/index.d.ts +3 -3
- package/dist/plugins/tenant/index.js +45 -21
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +4 -3
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +26 -6
- package/dist/{pool-B9qsLyFR.d.ts → pool-C9voM4Kw.d.ts} +24 -6
- package/dist/postgres/index.d.ts +5 -5
- package/dist/postgres/index.js +20 -10
- package/dist/{postgrest-DmBlevh-.d.ts → postgrest-CruYKAvV.d.ts} +1 -1
- package/dist/{problem-CGt1ADix.js → problem-BW1KhzSG.js} +2 -1
- package/dist/{problem-Z2RTQjZD.d.ts → problem-Blxe8S31.d.ts} +1 -1
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +3 -3
- package/dist/{query-BdKLTPlj.js → query-CCbo44lG.js} +18 -18
- package/dist/queue-BYUCjr59.d.ts +252 -0
- package/dist/react/index.d.ts +8 -7
- package/dist/react/index.js +4 -3
- package/dist/react/server.d.ts +16 -5
- package/dist/react/server.js +12 -4
- package/dist/react/session.d.ts +10 -4
- package/dist/react/session.js +11 -3
- package/dist/{react-DNBYNazu.js → react-C_s7kiNz.js} +138 -46
- package/dist/{read-set-D0qBcboM.js → read-set-DQFt1N_Y.js} +71 -15
- package/dist/realtime/index.d.ts +3 -3
- package/dist/realtime/index.js +14 -12
- package/dist/{index-kpgopLNv.d.ts → refresh-BTrQ_ZTp.d.ts} +6 -3
- package/dist/{resolve-BRciX2jK.d.ts → resolve-C15TJq77.d.ts} +22 -11
- package/dist/{resource-D30rp0GN.js → resource-CRxxwkQq.js} +24 -9
- package/dist/{resource-CwVgiI5q.d.ts → resource-D8iqWMr-.d.ts} +6 -6
- package/dist/respond-D2OQl62-.d.ts +371 -0
- package/dist/{result-DWXatkd6.js → result-BKiliPY7.js} +2 -2
- package/dist/server/index.d.ts +17 -15
- package/dist/server/index.js +16 -22
- package/dist/server-Csx2sRjg.js +655 -0
- package/dist/{shared-_6-uPL7E.js → shared-D1dRUrAg.js} +19 -4
- package/dist/signers-Cc6r98SW.d.ts +162 -0
- package/dist/{simplify-LakqK1vH.js → simplify-_0oUKqCd.js} +27 -95
- package/dist/sql/index.d.ts +247 -10
- package/dist/sql/index.js +8591 -780
- package/dist/{sql-BIgk12ew.js → sql-Coh6n4cC.js} +11 -3
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.js +1 -2
- package/dist/{standard-FUi3Z3-7.js → standard-D7r6dMUu.js} +6 -3
- package/dist/{standard-eudBiRk1.d.ts → standard-J4YgMOLm.d.ts} +1 -1
- package/dist/{stats-D78UQ8Yu.js → stats-Bqob3WqT.js} +34 -9
- package/dist/storage/index.d.ts +4 -4
- package/dist/storage/index.js +174 -27
- package/dist/support-DT-OhSxD.d.ts +88 -0
- package/dist/support-Dk6vdmEw.js +291 -0
- package/dist/support-view-Da5peKFg.d.ts +17 -0
- package/dist/support-view-g4YLBeqX.js +18 -0
- package/dist/{tables-Dhha3BXM.js → tables-Cb-3_VWc.js} +14 -0
- package/dist/{permdock-sql-Bta_G0v-.js → template-TxrGI5jR.js} +2 -31
- package/dist/{temporal-BwshQk0W.js → temporal-CVlIV2DZ.js} +17 -4
- package/dist/{temporal-required-CMxeSVPo.js → temporal-required-CAt4Dc9Z.js} +2 -2
- package/dist/testing/index.d.ts +113 -24
- package/dist/testing/index.js +375 -47
- package/dist/{types-DONv9SHN.d.ts → types-Dnf_wRDz.d.ts} +26 -3
- package/dist/user-change-CHFEUro1.js +49 -0
- package/dist/{webhooks-CAIFQSTM.js → verify-Ce49ETPz.js} +38 -19
- package/dist/{version-BfpG2gks.js → version-DM_Roffb.js} +1 -1
- package/dist/{view-3Po_PVlr.d.ts → view-BEf0diC5.d.ts} +10 -5
- package/dist/{mfa-BxoR1RkN.js → view-Bq64ki8-.js} +210 -64
- package/dist/webhooks/index.d.ts +136 -5
- package/dist/webhooks/index.js +588 -2
- package/dist/wire-D2dT86vi.js +35 -0
- package/package.json +50 -10
- package/schemas/config-v1.json +131 -1
- package/schemas/doctor-report-v1.json +10 -0
- package/skills/better-supabase/SKILL.md +60 -10
- package/skills/better-supabase/references/plugins.md +13 -14
- package/skills/better-supabase/references/troubleshooting.md +25 -4
- package/skills/better-supabase-api/SKILL.md +74 -19
- package/skills/better-supabase-api/references/adapters.md +48 -27
- package/skills/better-supabase-auth/SKILL.md +149 -0
- package/skills/better-supabase-auth/references/permdock.md +100 -0
- package/skills/better-supabase-testing/SKILL.md +58 -4
- package/dist/claims-CoTobNC-.js +0 -25
- package/dist/events-Do8jXh4D.d.ts +0 -84
- package/dist/executor-DynmIWhq.d.ts +0 -195
- package/dist/invalidate-DbxuL2jL.js +0 -18
- package/dist/permdock-sql-DImJULY-.d.ts +0 -17
- package/dist/plugin-BqR6wKMB.js +0 -23
- package/dist/respond-C44EZAJo.js +0 -399
- package/dist/respond-DAkPIdTH.d.ts +0 -175
- package/dist/result-c2OYgCV2.d.ts +0 -203
- package/dist/view-wZ-9qIUz.js +0 -45
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
import { r as defineCliCommand } from "./command-CK14fP91.js";
|
|
2
|
+
import { r as writeIfChanged } from "./io-k41_z-jT.js";
|
|
3
|
+
import { i as plain, r as painter } from "./style-C0NFdJRL.js";
|
|
4
|
+
import { t as fileDiff } from "./diff-SjkO5rNr.js";
|
|
5
|
+
import { extname, join, relative, resolve } from "node:path";
|
|
6
|
+
import { readFile, readdir, stat } from "node:fs/promises";
|
|
7
|
+
//#region src/cli/codemod.ts
|
|
8
|
+
const CODEMODS = {
|
|
9
|
+
"0.4": {
|
|
10
|
+
name: "0.4",
|
|
11
|
+
description: "Renames from 0.3 to 0.4 (the naming page lists them)",
|
|
12
|
+
imports: {
|
|
13
|
+
createBrowser: "createClient",
|
|
14
|
+
BetterBrowser: "BetterClient",
|
|
15
|
+
BrowserOptions: "ClientOptions",
|
|
16
|
+
BrowserAuth: "ClientAuth",
|
|
17
|
+
BetterEnv: "HonoEnv",
|
|
18
|
+
HandlerOptions: "MiddlewareOptions",
|
|
19
|
+
Queries: "BetterQueries",
|
|
20
|
+
CreateQueriesOptions: "QueriesOptions",
|
|
21
|
+
Postgres: "BetterPostgres",
|
|
22
|
+
DefineSupabaseOptions: "SupabaseOptions"
|
|
23
|
+
},
|
|
24
|
+
members: [
|
|
25
|
+
{
|
|
26
|
+
from: "serverFor",
|
|
27
|
+
to: "contextForSession"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
from: "toORPCError",
|
|
31
|
+
to: "toOrpcError"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
from: "$table",
|
|
35
|
+
to: "$tableName",
|
|
36
|
+
notCalled: true
|
|
37
|
+
}
|
|
38
|
+
],
|
|
39
|
+
props: [{
|
|
40
|
+
component: "BetterSupabaseProvider",
|
|
41
|
+
from: "browser",
|
|
42
|
+
to: "client"
|
|
43
|
+
}],
|
|
44
|
+
review: [
|
|
45
|
+
{
|
|
46
|
+
pattern: /\.server\(\)/,
|
|
47
|
+
message: "`next.server()` is `bs.context()` on the createNext() instance"
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
pattern: /\.handle\(\)/,
|
|
51
|
+
message: "Hono's `bs.handle()` is `bs.handler()`"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
pattern: /\bmcp\.handler\b/,
|
|
55
|
+
message: "`mcp.handler` is `bs.endpoint`"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
pattern: /\.sb\b/,
|
|
59
|
+
message: "`client.sb` is `client.betterSupabase`"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
pattern: /\btestExecutor\(\s*\{[^}]*\bsb\b/,
|
|
63
|
+
message: "`{ sb }` in testExecutor is `{ betterSupabase }`"
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
},
|
|
67
|
+
"0.5": {
|
|
68
|
+
name: "0.5",
|
|
69
|
+
description: "Renames from 0.4 to 0.5: createMcp's scopes is advertisedScopes",
|
|
70
|
+
options: [{
|
|
71
|
+
call: "createMcp",
|
|
72
|
+
from: "scopes",
|
|
73
|
+
to: "advertisedScopes"
|
|
74
|
+
}]
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
/** `[start, end)` ranges of code, outside strings, template literals and comments. */
|
|
78
|
+
function codeRanges(text) {
|
|
79
|
+
const ranges = [];
|
|
80
|
+
let start = 0;
|
|
81
|
+
let index = 0;
|
|
82
|
+
const skip = (end) => {
|
|
83
|
+
if (index > start) ranges.push([start, index]);
|
|
84
|
+
index = end;
|
|
85
|
+
start = end;
|
|
86
|
+
};
|
|
87
|
+
while (index < text.length) {
|
|
88
|
+
const char = text[index];
|
|
89
|
+
const next = text[index + 1];
|
|
90
|
+
if (char === "/" && next === "/") {
|
|
91
|
+
const end = text.indexOf("\n", index);
|
|
92
|
+
skip(end === -1 ? text.length : end);
|
|
93
|
+
} else if (char === "/" && next === "*") {
|
|
94
|
+
const end = text.indexOf("*/", index + 2);
|
|
95
|
+
skip(end === -1 ? text.length : end + 2);
|
|
96
|
+
} else if (char === "\"" || char === "'" || char === "`") {
|
|
97
|
+
let end = index + 1;
|
|
98
|
+
while (end < text.length && text[end] !== char) {
|
|
99
|
+
if (text[end] === "\\") end += 1;
|
|
100
|
+
if (char !== "`" && text[end] === "\n") break;
|
|
101
|
+
end += 1;
|
|
102
|
+
}
|
|
103
|
+
skip(text[end] === char ? end + 1 : Math.min(end, text.length));
|
|
104
|
+
} else index += 1;
|
|
105
|
+
}
|
|
106
|
+
if (index > start) ranges.push([start, index]);
|
|
107
|
+
return ranges;
|
|
108
|
+
}
|
|
109
|
+
function applyEdits(text, edits) {
|
|
110
|
+
let out = "";
|
|
111
|
+
let cursor = 0;
|
|
112
|
+
for (const edit of [...edits].sort((a, b) => a.start - b.start)) {
|
|
113
|
+
if (edit.start < cursor) continue;
|
|
114
|
+
out += text.slice(cursor, edit.start) + edit.text;
|
|
115
|
+
cursor = edit.end;
|
|
116
|
+
}
|
|
117
|
+
return out + text.slice(cursor);
|
|
118
|
+
}
|
|
119
|
+
const escapeRegExp = (value) => value.replaceAll(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
120
|
+
function inCode(ranges, index) {
|
|
121
|
+
let low = 0;
|
|
122
|
+
let high = ranges.length - 1;
|
|
123
|
+
while (low <= high) {
|
|
124
|
+
const middle = low + high >> 1;
|
|
125
|
+
const [start, end] = ranges[middle];
|
|
126
|
+
if (index < start) high = middle - 1;
|
|
127
|
+
else if (index >= end) low = middle + 1;
|
|
128
|
+
else return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
const OPENING = "({[";
|
|
133
|
+
const CLOSING = ")}]";
|
|
134
|
+
/** Matches of `pattern` that start in code. */
|
|
135
|
+
function codeMatches(text, pattern, ranges) {
|
|
136
|
+
return [...text.matchAll(pattern)].filter((match) => inCode(ranges, match.index));
|
|
137
|
+
}
|
|
138
|
+
const IMPORT = /\b(import|export)\s+(type\s+)?\{([^}]*)\}\s*from\s*(["'])better-supabase(?:\/[\w./-]*)?\4/g;
|
|
139
|
+
function renameImports(text, renames) {
|
|
140
|
+
const ranges = codeRanges(text);
|
|
141
|
+
const locals = /* @__PURE__ */ new Set();
|
|
142
|
+
const edits = [];
|
|
143
|
+
for (const match of codeMatches(text, IMPORT, ranges)) {
|
|
144
|
+
const list = match[3];
|
|
145
|
+
const listStart = match.index + match[0].indexOf("{") + 1;
|
|
146
|
+
const renamed = list.replaceAll(/(\btype\s+)?([\w$]+)(\s+as\s+[\w$]+)?/g, (spec, type, name, alias) => {
|
|
147
|
+
const to = renames[name];
|
|
148
|
+
if (to === void 0) return spec;
|
|
149
|
+
if (alias === void 0 && match[1] === "import") locals.add(name);
|
|
150
|
+
return `${type ?? ""}${to}${alias ?? ""}`;
|
|
151
|
+
});
|
|
152
|
+
if (renamed !== list) edits.push({
|
|
153
|
+
start: listStart,
|
|
154
|
+
end: listStart + list.length,
|
|
155
|
+
text: renamed
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
return {
|
|
159
|
+
text: applyEdits(text, edits),
|
|
160
|
+
locals
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function renameIdentifiers(text, renames) {
|
|
164
|
+
if (renames.size === 0) return text;
|
|
165
|
+
const ranges = codeRanges(text);
|
|
166
|
+
const names = [...renames.keys()].map(escapeRegExp).join("|");
|
|
167
|
+
return applyEdits(text, codeMatches(text, new RegExp(`(?<![\\w$.])(?:${names})(?![\\w$])`, "g"), ranges).map((match) => ({
|
|
168
|
+
start: match.index,
|
|
169
|
+
end: match.index + match[0].length,
|
|
170
|
+
text: renames.get(match[0])
|
|
171
|
+
})));
|
|
172
|
+
}
|
|
173
|
+
function renameMembers(text, members) {
|
|
174
|
+
const ranges = codeRanges(text);
|
|
175
|
+
return applyEdits(text, members.flatMap((member) => codeMatches(text, new RegExp(`\\.${escapeRegExp(member.from)}(?![\\w$])${member.notCalled === true ? "(?!\\s*\\()" : ""}`, "g"), ranges).map((match) => ({
|
|
176
|
+
start: match.index,
|
|
177
|
+
end: match.index + match[0].length,
|
|
178
|
+
text: `.${member.to}`
|
|
179
|
+
}))));
|
|
180
|
+
}
|
|
181
|
+
function renameProps(text, props) {
|
|
182
|
+
const ranges = codeRanges(text);
|
|
183
|
+
const edits = [];
|
|
184
|
+
for (const prop of props) {
|
|
185
|
+
const tag = new RegExp(`<${escapeRegExp(prop.component)}(?![\\w$.])`, "g");
|
|
186
|
+
for (const match of codeMatches(text, tag, ranges)) {
|
|
187
|
+
let depth = 0;
|
|
188
|
+
for (let index = match.index + match[0].length; index < text.length; index += 1) {
|
|
189
|
+
if (!inCode(ranges, index)) continue;
|
|
190
|
+
const char = text[index];
|
|
191
|
+
if (char === "{") depth += 1;
|
|
192
|
+
else if (char === "}") depth -= 1;
|
|
193
|
+
else if (char === ">" && depth === 0) break;
|
|
194
|
+
if (depth === 0 && /\s/.test(text[index - 1] ?? "") && text.startsWith(`${prop.from}=`, index)) edits.push({
|
|
195
|
+
start: index,
|
|
196
|
+
end: index + prop.from.length,
|
|
197
|
+
text: prop.to
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return applyEdits(text, edits);
|
|
203
|
+
}
|
|
204
|
+
/** The index after the bracket that closes the one at `open`, in code only. */
|
|
205
|
+
function closing(text, open, ranges) {
|
|
206
|
+
let depth = 0;
|
|
207
|
+
for (let index = open; index < text.length; index += 1) {
|
|
208
|
+
if (!inCode(ranges, index)) continue;
|
|
209
|
+
const char = text[index];
|
|
210
|
+
if (OPENING.includes(char)) depth += 1;
|
|
211
|
+
else if (CLOSING.includes(char)) {
|
|
212
|
+
depth -= 1;
|
|
213
|
+
if (depth === 0) return index + 1;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return text.length;
|
|
217
|
+
}
|
|
218
|
+
/** Calls `visit(index, depth)` for each code character from `open` to its closing bracket. */
|
|
219
|
+
function walkBrackets(text, open, ranges, visit) {
|
|
220
|
+
const end = closing(text, open, ranges);
|
|
221
|
+
let depth = 0;
|
|
222
|
+
for (let index = open; index < end; index += 1) {
|
|
223
|
+
if (!inCode(ranges, index)) continue;
|
|
224
|
+
const char = text[index];
|
|
225
|
+
if (OPENING.includes(char)) depth += 1;
|
|
226
|
+
else if (CLOSING.includes(char)) depth -= 1;
|
|
227
|
+
visit(index, depth, char);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/** Where `key` is a top-level key of the object literal at `open`. */
|
|
231
|
+
function topLevelKeys(text, open, key, ranges) {
|
|
232
|
+
const keys = [];
|
|
233
|
+
let previous = "";
|
|
234
|
+
walkBrackets(text, open, ranges, (index, depth, char) => {
|
|
235
|
+
if (depth === 1 && (previous === "{" || previous === ",") && text.startsWith(key, index) && !/[\w$]/.test(text[index + key.length] ?? "")) {
|
|
236
|
+
const after = /^\s*(\S)/.exec(text.slice(index + key.length))?.[1];
|
|
237
|
+
if (after === ":") keys.push({
|
|
238
|
+
index,
|
|
239
|
+
shorthand: false
|
|
240
|
+
});
|
|
241
|
+
else if (after === "," || after === "}") keys.push({
|
|
242
|
+
index,
|
|
243
|
+
shorthand: true
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
if (depth === 1 && !/\s/.test(char)) previous = char;
|
|
247
|
+
});
|
|
248
|
+
return keys;
|
|
249
|
+
}
|
|
250
|
+
function renameOptions(text, options) {
|
|
251
|
+
const ranges = codeRanges(text);
|
|
252
|
+
const edits = [];
|
|
253
|
+
for (const option of options) {
|
|
254
|
+
const call = new RegExp(`(?<![\\w$.])${escapeRegExp(option.call)}\\s*(?:<[^>]*>)?\\s*\\(`, "g");
|
|
255
|
+
for (const match of codeMatches(text, call, ranges)) {
|
|
256
|
+
const objects = [];
|
|
257
|
+
walkBrackets(text, match.index + match[0].length - 1, ranges, (index, depth, char) => {
|
|
258
|
+
if (depth === 2 && char === "{") objects.push(index);
|
|
259
|
+
});
|
|
260
|
+
for (const object of objects) for (const { index, shorthand } of topLevelKeys(text, object, option.from, ranges)) edits.push({
|
|
261
|
+
start: index,
|
|
262
|
+
end: index + option.from.length,
|
|
263
|
+
text: shorthand ? `${option.to}: ${option.from}` : option.to
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return applyEdits(text, edits);
|
|
268
|
+
}
|
|
269
|
+
/** Applies one codemod to a source file. */
|
|
270
|
+
function applyCodemod(codemod, source) {
|
|
271
|
+
let text = source;
|
|
272
|
+
if (codemod.imports) {
|
|
273
|
+
const imported = renameImports(text, codemod.imports);
|
|
274
|
+
text = renameIdentifiers(imported.text, new Map([...imported.locals].map((name) => [name, codemod.imports[name]])));
|
|
275
|
+
}
|
|
276
|
+
if (codemod.members) text = renameMembers(text, codemod.members);
|
|
277
|
+
if (codemod.props) text = renameProps(text, codemod.props);
|
|
278
|
+
if (codemod.options) text = renameOptions(text, codemod.options);
|
|
279
|
+
const review = (codemod.review ?? []).flatMap((hint) => text.split("\n").flatMap((line, index) => hint.pattern.test(line) ? [{
|
|
280
|
+
line: index + 1,
|
|
281
|
+
message: hint.message
|
|
282
|
+
}] : []));
|
|
283
|
+
return {
|
|
284
|
+
text,
|
|
285
|
+
review
|
|
286
|
+
};
|
|
287
|
+
}
|
|
288
|
+
//#endregion
|
|
289
|
+
//#region src/cli/commands/codemod.ts
|
|
290
|
+
const CODEMOD_ARGS = {
|
|
291
|
+
name: {
|
|
292
|
+
type: "positional",
|
|
293
|
+
required: false,
|
|
294
|
+
description: "The codemod (0.4 or 0.5), then the files or directories to rewrite (default: the project)"
|
|
295
|
+
},
|
|
296
|
+
"dry-run": {
|
|
297
|
+
type: "boolean",
|
|
298
|
+
description: "Show the changes without writing them"
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
302
|
+
".ts",
|
|
303
|
+
".tsx",
|
|
304
|
+
".mts",
|
|
305
|
+
".cts",
|
|
306
|
+
".js",
|
|
307
|
+
".jsx",
|
|
308
|
+
".mjs",
|
|
309
|
+
".cjs"
|
|
310
|
+
]);
|
|
311
|
+
const SKIPPED_DIRS = /* @__PURE__ */ new Set([
|
|
312
|
+
"node_modules",
|
|
313
|
+
".git",
|
|
314
|
+
".next",
|
|
315
|
+
".turbo",
|
|
316
|
+
".vercel",
|
|
317
|
+
"dist",
|
|
318
|
+
"build",
|
|
319
|
+
"coverage"
|
|
320
|
+
]);
|
|
321
|
+
/** Source files under `path`, skipping dependencies, build output and `.d.ts` files. */
|
|
322
|
+
async function sourceFiles(path) {
|
|
323
|
+
const info = await stat(path).catch(() => void 0);
|
|
324
|
+
if (!info) return [];
|
|
325
|
+
if (info.isFile()) return [path];
|
|
326
|
+
const files = [];
|
|
327
|
+
for (const entry of await readdir(path, { withFileTypes: true })) {
|
|
328
|
+
const full = join(path, entry.name);
|
|
329
|
+
if (entry.isDirectory()) {
|
|
330
|
+
if (!SKIPPED_DIRS.has(entry.name)) files.push(...await sourceFiles(full));
|
|
331
|
+
} else if (SOURCE_EXTENSIONS.has(extname(entry.name)) && !entry.name.endsWith(".d.ts")) files.push(full);
|
|
332
|
+
}
|
|
333
|
+
return files.sort();
|
|
334
|
+
}
|
|
335
|
+
async function runCodemod(config, args, paint = plain) {
|
|
336
|
+
const [name, ...paths] = args._;
|
|
337
|
+
const names = Object.entries(CODEMODS).map(([key, codemod]) => ` ${key.padEnd(5)} ${codemod.description}`).join("\n");
|
|
338
|
+
if (name === void 0) return {
|
|
339
|
+
code: 2,
|
|
340
|
+
error: `Name a codemod:\n${names}`
|
|
341
|
+
};
|
|
342
|
+
const codemod = CODEMODS[name];
|
|
343
|
+
if (!codemod) return {
|
|
344
|
+
code: 2,
|
|
345
|
+
error: `Unknown codemod "${name}". Codemods:\n${names}`
|
|
346
|
+
};
|
|
347
|
+
const roots = (paths.length > 0 ? paths : ["."]).map((path) => resolve(config.root, path));
|
|
348
|
+
const files = [...new Set((await Promise.all(roots.map(sourceFiles))).flat())];
|
|
349
|
+
const dryRun = args["dry-run"] === true;
|
|
350
|
+
const changed = [];
|
|
351
|
+
const diffs = [];
|
|
352
|
+
const review = [];
|
|
353
|
+
for (const file of files) {
|
|
354
|
+
const source = await readFile(file, "utf8");
|
|
355
|
+
const result = applyCodemod(codemod, source);
|
|
356
|
+
const path = relative(config.root, file);
|
|
357
|
+
review.push(...result.review.map((hint) => ({
|
|
358
|
+
file: path,
|
|
359
|
+
...hint
|
|
360
|
+
})));
|
|
361
|
+
if (result.text === source) continue;
|
|
362
|
+
changed.push(path);
|
|
363
|
+
if (dryRun) diffs.push(fileDiff(path, source, result.text, paint));
|
|
364
|
+
else await writeIfChanged(file, result.text);
|
|
365
|
+
}
|
|
366
|
+
const lines = [...diffs, changed.length === 0 ? `Nothing to change in ${String(files.length)} files.` : `${dryRun ? "Would update" : "Updated"} ${String(changed.length)} of ${String(files.length)} files:\n${changed.map((path) => ` ${path}`).join("\n")}`];
|
|
367
|
+
if (review.length > 0) lines.push("", "Check these by hand:", ...review.map((hint) => ` ${hint.file}:${String(hint.line)}: ${hint.message}`));
|
|
368
|
+
return {
|
|
369
|
+
code: 0,
|
|
370
|
+
output: lines.join("\n"),
|
|
371
|
+
data: {
|
|
372
|
+
codemod: codemod.name,
|
|
373
|
+
dryRun,
|
|
374
|
+
changed,
|
|
375
|
+
review
|
|
376
|
+
}
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
const codemodCommand = defineCliCommand({
|
|
380
|
+
meta: {
|
|
381
|
+
name: "codemod",
|
|
382
|
+
description: "Rewrites imports and calls for renamed better-supabase APIs"
|
|
383
|
+
},
|
|
384
|
+
args: CODEMOD_ARGS,
|
|
385
|
+
run: (args, { config, io }) => runCodemod(config, args, painter(io.color))
|
|
386
|
+
});
|
|
387
|
+
//#endregion
|
|
388
|
+
export { codemodCommand };
|