better-supabase 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -33
- package/dist/base64-D2gsioCY.js +42 -0
- package/dist/claims-BAf6c7is.js +48 -0
- package/dist/cli/_format-Cax5EsM9.js +101 -0
- package/dist/cli/bin.js +39 -6
- package/dist/cli/command-CK14fP91.js +502 -0
- package/dist/cli/compare-BmIWVEui.js +9 -0
- package/dist/cli/config-D9R0o1LH.js +1895 -0
- package/dist/cli/config-SSKSTUl2.js +2 -0
- package/dist/cli/db-DOBPt660.js +52 -0
- package/dist/cli/dist-B1MvLv-M.js +129 -0
- package/dist/cli/dist-CFgGknmZ.js +1112 -0
- package/dist/cli/dist-Du7VnEUG.js +621 -0
- package/dist/cli/doctor-BOym3mbL.js +2382 -0
- package/dist/cli/env-BZ0uy8XK.js +108 -0
- package/dist/cli/env-jIFUADLY.js +511 -0
- package/dist/cli/errors-4v4DTtda.js +56 -0
- package/dist/cli/fastest-levenshtein-CFN-lNDv.js +120 -0
- package/dist/cli/gen-Ccn_p90L.js +2008 -0
- package/dist/cli/gen-D5cLCULx.js +2 -0
- package/dist/cli/index.d.ts +295 -28
- package/dist/cli/index.js +184 -3
- package/dist/cli/init-ClnxRYBF.js +550 -0
- package/dist/cli/introspect-DxqfkVIv.js +81 -0
- package/dist/cli/io-k41_z-jT.js +24 -0
- package/dist/cli/json5-ChRycquj.js +787 -0
- package/dist/cli/jsonc-BUniUpOk.js +2 -0
- package/dist/cli/jsonc-D5Fu67jw.js +45 -0
- package/dist/cli/keys-ByKHnvP9.js +83 -0
- package/dist/cli/ohash-D7bG_EOb.js +277 -0
- package/dist/cli/openapi-8WHjxiTJ.js +66 -0
- package/dist/cli/project-B_GeXyHh.js +70 -0
- package/dist/cli/prompts-BNcNfAve.js +1142 -0
- package/dist/cli/prompts-BTYQGunc.js +2 -0
- package/dist/cli/read-sets-CMa29t9a.js +971 -0
- package/dist/cli/rolldown-runtime-BPOCksWG.js +24 -0
- package/dist/cli/run-CP20LKk_.js +347 -0
- package/dist/cli/seed-5J6eu_Xg.js +98 -0
- package/dist/cli/skills-LJJIhLFR.js +137 -0
- package/dist/cli/sql-D4VbqmXi.js +199 -0
- package/dist/cli/style-C0NFdJRL.js +29 -0
- package/dist/cli/toml-DB-MNnFs.js +424 -0
- package/dist/{version-Cqq1m3UY.js → cli/version-5mW_8sY1.js} +1 -1
- package/dist/cli/yaml-CYCbJ6et.js +2252 -0
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +15 -25
- package/dist/{compiler-CZ9nIuqy.d.ts → compiler-DB3aSFOA.d.ts} +2 -2
- package/dist/config/index.d.ts +4 -3
- package/dist/config/index.js +5 -3
- package/dist/config-BpxDfnbg.js +129 -0
- package/dist/{index-DOsjFvMf.d.ts → config-C1CYcm6o.d.ts} +49 -49
- package/dist/{config-ClDXmVtY.js → config-CbvFmGD8.js} +14 -137
- package/dist/{define-BXMYD9AY.js → define-Bh0AqTik.js} +221 -120
- package/dist/{define-e3zI4_4g.d.ts → define-CRS2MRV3.d.ts} +36 -31
- package/dist/edge/index.d.ts +9 -13
- package/dist/edge/index.js +51 -25
- package/dist/{entitlements-Dng-ctuT.d.ts → entitlements-Dm-FHpNH.d.ts} +2 -2
- package/dist/env/index.js +203 -1
- package/dist/{errors-Bl3rkOzo.js → errors-L0xK41y_.js} +1 -1
- package/dist/events/index.d.ts +1 -1
- package/dist/events/index.js +139 -1
- package/dist/{events-DOt3nSO-.d.ts → events-B21UOhvP.d.ts} +4 -4
- package/dist/{executor-CGdNQ27g.d.ts → executor-B5IoUxLE.d.ts} +2 -2
- package/dist/{executor-DeppvirK.js → executor-CVt6dD0B.js} +9 -4
- package/dist/{executor-BYXQ9AGn.d.ts → executor-CZ7ImRiD.d.ts} +2 -2
- package/dist/hono/index.d.ts +17 -24
- package/dist/hono/index.js +11 -11
- package/dist/{index-DuP14VHo.d.ts → index-528Ugmyp.d.ts} +30 -10
- package/dist/{index-Bw1bwtC0.d.ts → index-BAy4tsAP.d.ts} +28 -15
- package/dist/{index-CBDufH1M.d.ts → index-BBdvo-5d.d.ts} +24 -26
- package/dist/{index-DbxFr7XG.d.ts → index-BhHEC04r.d.ts} +9 -4
- package/dist/index-Cf-D2jk1.d.ts +50 -0
- package/dist/{index-Ciu5Xlml.d.ts → index-D5IfUIDh.d.ts} +6 -5
- package/dist/{index-K-3WM2Hp.d.ts → index-DFmOpBGC.d.ts} +13 -13
- package/dist/{index-D4v7sncu.d.ts → index-RlLXd8dL.d.ts} +13 -13
- package/dist/index.d.ts +17 -17
- package/dist/index.js +23 -14
- package/dist/{invalidate-DbxuL2jL.js → invalidate-CgxmRamI.js} +7 -1
- package/dist/jobs/index.d.ts +33 -26
- package/dist/jobs/index.js +44 -22
- package/dist/{json-schema-BpYqkCKf.js → json-schema-DP6V7cbr.js} +8 -3
- package/dist/lint/index.js +1 -1
- package/dist/list/index.d.ts +2 -2
- package/dist/list/index.js +131 -96
- package/dist/{live-DJyZMD6w.d.ts → live-BHakSWWo.d.ts} +26 -16
- package/dist/{live-D8rV1Ldw.js → live-CdJBOc4f.js} +13 -9
- package/dist/lookup-BaP5bI27.js +18 -0
- package/dist/mcp/index.d.ts +34 -27
- package/dist/mcp/index.js +59 -25
- package/dist/{mfa-TVia554c.d.ts → mfa-C7MNQ1Ob.d.ts} +1 -1
- package/dist/{mfa-CpLfJSde.js → mfa-byfjruR9.js} +190 -46
- package/dist/next/image/index.js +6 -3
- package/dist/next/index.d.ts +64 -48
- package/dist/next/index.js +63 -50
- package/dist/openapi/index.d.ts +1 -1
- package/dist/openapi/index.js +61 -38
- package/dist/orpc/index.d.ts +18 -21
- package/dist/orpc/index.js +12 -12
- package/dist/otel/index.d.ts +5 -5
- package/dist/otel/index.js +84 -63
- package/dist/{permdock-sql-CghlHPuH.js → permdock-sql-C4KFzLc9.js} +12 -7
- package/dist/permdock-sql-DImJULY-.d.ts +17 -0
- package/dist/{plugin-C4TR9J0Z.d.ts → plugin-bNhvJwRh.d.ts} +5 -4
- package/dist/plugins/actor/index.d.ts +1 -1
- package/dist/plugins/actor/index.js +1 -1
- package/dist/plugins/rules/index.d.ts +2 -2
- package/dist/plugins/rules/index.js +46 -16
- package/dist/plugins/soft-delete/index.d.ts +3 -3
- package/dist/plugins/soft-delete/index.js +4 -4
- package/dist/plugins/tenant/index.d.ts +3 -3
- package/dist/plugins/tenant/index.js +10 -4
- package/dist/plugins/timestamps/index.d.ts +1 -1
- package/dist/plugins/timestamps/index.js +2 -2
- package/dist/plugins/validation/index.d.ts +2 -2
- package/dist/plugins/validation/index.js +3 -3
- package/dist/pool-DFwEQwmN.d.ts +78 -0
- package/dist/postgres/index.d.ts +10 -5
- package/dist/postgres/index.js +37 -16
- package/dist/{postgrest-cAEQ_IQN.d.ts → postgrest-Bc-0Xw62.d.ts} +1 -1
- package/dist/{problem-BTkTtRV9.js → problem-BihjPR0t.js} +11 -5
- package/dist/{problem-DlgB0lYl.d.ts → problem-U8UEKccv.d.ts} +6 -4
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +2 -2
- package/dist/{query-ChvDbsDE.js → query-BMMSWbI7.js} +19 -19
- package/dist/react/index.d.ts +7 -7
- package/dist/react/index.js +2 -2
- package/dist/react/server.d.ts +6 -6
- package/dist/react/server.js +3 -3
- package/dist/react/session.d.ts +21 -2
- package/dist/react/session.js +19 -1
- package/dist/{react-C83BdBGt.js → react-CQHMaESR.js} +59 -55
- package/dist/{read-set-4lI3W_gZ.js → read-set-FWK8qQ58.js} +51 -16
- package/dist/realtime/index.d.ts +4 -3
- package/dist/realtime/index.js +19 -17
- package/dist/{index-CG69s15v.d.ts → refresh-BwYkyNOQ.d.ts} +7 -3
- package/dist/{resolve-CjHILk2w.d.ts → resolve-BAqQcwMW.d.ts} +17 -11
- package/dist/{resource-CgZa3YG_.d.ts → resource-BJcaIfxi.d.ts} +17 -8
- package/dist/{resource-BHEWmQJK.js → resource-My_y-Syh.js} +43 -21
- package/dist/{respond-Dne1ARSa.d.ts → respond-DgIbdrt8.d.ts} +39 -14
- package/dist/{result-DWXatkd6.js → result-Bj6yt33D.js} +2 -2
- package/dist/{result-CTkCZ6JA.d.ts → result-CqEsbgYs.d.ts} +16 -11
- package/dist/server/index.d.ts +38 -13
- package/dist/server/index.js +43 -14
- package/dist/{respond-DMcbQwfN.js → server-BA75B0mT.js} +151 -96
- package/dist/{shared-_6-uPL7E.js → shared-DnoCdMDr.js} +4 -3
- package/dist/{simplify-bwJpLnaS.js → simplify-Cqvfr9dj.js} +76 -39
- package/dist/sql/index.d.ts +139 -0
- package/dist/sql/index.js +1983 -0
- package/dist/{sql-DTjA1LPj.js → sql-B34HU2DI.js} +74 -17
- package/dist/ssr/index.d.ts +4 -4
- package/dist/ssr/index.js +2 -2
- package/dist/{standard-FUi3Z3-7.js → standard-BRyBGTtp.js} +2 -2
- package/dist/{standard-CyhRzctb.d.ts → standard-BsaCYQJc.d.ts} +1 -1
- package/dist/{stats-C5W-rBfR.js → stats-C_YxA2r1.js} +40 -14
- package/dist/storage/index.d.ts +4 -3
- package/dist/storage/index.js +548 -1
- package/dist/{tables-rZxRxNPW.js → tables-Cb-3_VWc.js} +19 -5
- package/dist/temporal-BwshQk0W.js +27 -0
- package/dist/temporal-required-CBNHT6ni.js +19 -0
- package/dist/testing/index.d.ts +25 -24
- package/dist/testing/index.js +165 -66
- package/dist/{types-C83v5SQz.d.ts → types-DONv9SHN.d.ts} +14 -11
- package/dist/version-Bmf7_FzM.js +4 -0
- package/dist/{view-D1s0wa0T.d.ts → view-B64o81wp.d.ts} +36 -6
- package/dist/{view-aOYizTeE.js → view-BrJI2LKp.js} +11 -2
- package/dist/webhooks/index.d.ts +19 -17
- package/dist/webhooks/index.js +1 -1
- package/dist/{webhooks-DMipjhSP.js → webhooks-Bh_Jf_-l.js} +45 -24
- package/package.json +50 -22
- package/schemas/config-v1.json +31 -1
- package/schemas/doctor-report-v1.json +17 -1
- package/schemas/snapshot-v2.json +35 -0
- package/skills/better-supabase/SKILL.md +77 -18
- package/skills/better-supabase/references/plugins.md +21 -22
- package/skills/better-supabase/references/troubleshooting.md +38 -18
- package/skills/better-supabase-api/SKILL.md +66 -18
- package/skills/better-supabase-api/references/adapters.md +64 -41
- package/skills/better-supabase-auth/SKILL.md +146 -0
- package/skills/better-supabase-auth/references/permdock.md +55 -0
- package/skills/better-supabase-testing/SKILL.md +68 -11
- package/dist/casing-da0uRTqt.js +0 -14
- package/dist/claims-CoTobNC-.js +0 -25
- package/dist/cli-DrSgDOQC.js +0 -6646
- package/dist/env-BEToab0I.js +0 -204
- package/dist/events-BuzTgn2D.js +0 -135
- package/dist/pool-R2m_DkXi.d.ts +0 -37
- package/dist/seed-CzecODcJ.js +0 -101
- package/dist/session-C3LxnQ0e.d.ts +0 -22
- package/dist/session-CqEwzVup.js +0 -20
- package/dist/storage-DuGn38fr.js +0 -527
|
@@ -0,0 +1,971 @@
|
|
|
1
|
+
import { i as plain } from "./style-C0NFdJRL.js";
|
|
2
|
+
import { i as importModule } from "./config-D9R0o1LH.js";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { existsSync } from "node:fs";
|
|
5
|
+
import { readFile } from "node:fs/promises";
|
|
6
|
+
import { compileReadSets } from "better-supabase/sql";
|
|
7
|
+
import { isReadSet } from "better-supabase";
|
|
8
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/base.js
|
|
9
|
+
var Diff = class {
|
|
10
|
+
diff(oldStr, newStr, options = {}) {
|
|
11
|
+
let callback;
|
|
12
|
+
if (typeof options === "function") {
|
|
13
|
+
callback = options;
|
|
14
|
+
options = {};
|
|
15
|
+
} else if ("callback" in options) callback = options.callback;
|
|
16
|
+
const oldString = this.castInput(oldStr, options);
|
|
17
|
+
const newString = this.castInput(newStr, options);
|
|
18
|
+
const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
|
|
19
|
+
const newTokens = this.removeEmpty(this.tokenize(newString, options));
|
|
20
|
+
return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
|
|
21
|
+
}
|
|
22
|
+
diffWithOptionsObj(oldTokens, newTokens, options, callback) {
|
|
23
|
+
var _a;
|
|
24
|
+
const done = (value) => {
|
|
25
|
+
value = this.postProcess(value, options);
|
|
26
|
+
if (callback) {
|
|
27
|
+
setTimeout(function() {
|
|
28
|
+
callback(value);
|
|
29
|
+
}, 0);
|
|
30
|
+
return;
|
|
31
|
+
} else return value;
|
|
32
|
+
};
|
|
33
|
+
const newLen = newTokens.length, oldLen = oldTokens.length;
|
|
34
|
+
let editLength = 1;
|
|
35
|
+
let maxEditLength = newLen + oldLen;
|
|
36
|
+
if (options.maxEditLength != null) maxEditLength = Math.min(maxEditLength, options.maxEditLength);
|
|
37
|
+
const maxExecutionTime = (_a = options.timeout) !== null && _a !== void 0 ? _a : Infinity;
|
|
38
|
+
const abortAfterTimestamp = Date.now() + maxExecutionTime;
|
|
39
|
+
const bestPath = [{
|
|
40
|
+
oldPos: -1,
|
|
41
|
+
lastComponent: void 0
|
|
42
|
+
}];
|
|
43
|
+
let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
|
|
44
|
+
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
|
|
45
|
+
let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
|
|
46
|
+
const execEditLength = () => {
|
|
47
|
+
for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
|
|
48
|
+
let basePath;
|
|
49
|
+
const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
|
|
50
|
+
if (removePath) bestPath[diagonalPath - 1] = void 0;
|
|
51
|
+
let canAdd = false;
|
|
52
|
+
if (addPath) {
|
|
53
|
+
const addPathNewPos = addPath.oldPos - diagonalPath;
|
|
54
|
+
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
|
|
55
|
+
}
|
|
56
|
+
const canRemove = removePath && removePath.oldPos + 1 < oldLen;
|
|
57
|
+
if (!canAdd && !canRemove) {
|
|
58
|
+
bestPath[diagonalPath] = void 0;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) basePath = this.addToPath(addPath, true, false, 0, options);
|
|
62
|
+
else basePath = this.addToPath(removePath, false, true, 1, options);
|
|
63
|
+
newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
|
|
64
|
+
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
|
|
65
|
+
else {
|
|
66
|
+
bestPath[diagonalPath] = basePath;
|
|
67
|
+
if (basePath.oldPos + 1 >= oldLen) maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
|
|
68
|
+
if (newPos + 1 >= newLen) minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
editLength++;
|
|
72
|
+
};
|
|
73
|
+
if (callback) (function exec() {
|
|
74
|
+
setTimeout(function() {
|
|
75
|
+
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) return callback(void 0);
|
|
76
|
+
if (!execEditLength()) exec();
|
|
77
|
+
}, 0);
|
|
78
|
+
})();
|
|
79
|
+
else while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
|
|
80
|
+
const ret = execEditLength();
|
|
81
|
+
if (ret) return ret;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
addToPath(path, added, removed, oldPosInc, options) {
|
|
85
|
+
const last = path.lastComponent;
|
|
86
|
+
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) return {
|
|
87
|
+
oldPos: path.oldPos + oldPosInc,
|
|
88
|
+
lastComponent: {
|
|
89
|
+
count: last.count + 1,
|
|
90
|
+
added,
|
|
91
|
+
removed,
|
|
92
|
+
previousComponent: last.previousComponent
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
else return {
|
|
96
|
+
oldPos: path.oldPos + oldPosInc,
|
|
97
|
+
lastComponent: {
|
|
98
|
+
count: 1,
|
|
99
|
+
added,
|
|
100
|
+
removed,
|
|
101
|
+
previousComponent: last
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
|
|
106
|
+
const newLen = newTokens.length, oldLen = oldTokens.length;
|
|
107
|
+
let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
|
|
108
|
+
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
|
|
109
|
+
newPos++;
|
|
110
|
+
oldPos++;
|
|
111
|
+
commonCount++;
|
|
112
|
+
if (options.oneChangePerToken) basePath.lastComponent = {
|
|
113
|
+
count: 1,
|
|
114
|
+
previousComponent: basePath.lastComponent,
|
|
115
|
+
added: false,
|
|
116
|
+
removed: false
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
if (commonCount && !options.oneChangePerToken) basePath.lastComponent = {
|
|
120
|
+
count: commonCount,
|
|
121
|
+
previousComponent: basePath.lastComponent,
|
|
122
|
+
added: false,
|
|
123
|
+
removed: false
|
|
124
|
+
};
|
|
125
|
+
basePath.oldPos = oldPos;
|
|
126
|
+
return newPos;
|
|
127
|
+
}
|
|
128
|
+
equals(left, right, options) {
|
|
129
|
+
if (options.comparator) return options.comparator(left, right);
|
|
130
|
+
else return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
|
|
131
|
+
}
|
|
132
|
+
removeEmpty(array) {
|
|
133
|
+
const ret = [];
|
|
134
|
+
for (let i = 0; i < array.length; i++) if (array[i]) ret.push(array[i]);
|
|
135
|
+
return ret;
|
|
136
|
+
}
|
|
137
|
+
castInput(value, options) {
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
tokenize(value, options) {
|
|
141
|
+
return Array.from(value);
|
|
142
|
+
}
|
|
143
|
+
join(chars) {
|
|
144
|
+
return chars.join("");
|
|
145
|
+
}
|
|
146
|
+
postProcess(changeObjects, options) {
|
|
147
|
+
return changeObjects;
|
|
148
|
+
}
|
|
149
|
+
get useLongestToken() {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
buildValues(lastComponent, newTokens, oldTokens) {
|
|
153
|
+
const components = [];
|
|
154
|
+
let nextComponent;
|
|
155
|
+
while (lastComponent) {
|
|
156
|
+
components.push(lastComponent);
|
|
157
|
+
nextComponent = lastComponent.previousComponent;
|
|
158
|
+
delete lastComponent.previousComponent;
|
|
159
|
+
lastComponent = nextComponent;
|
|
160
|
+
}
|
|
161
|
+
components.reverse();
|
|
162
|
+
const componentLen = components.length;
|
|
163
|
+
let componentPos = 0, newPos = 0, oldPos = 0;
|
|
164
|
+
for (; componentPos < componentLen; componentPos++) {
|
|
165
|
+
const component = components[componentPos];
|
|
166
|
+
if (!component.removed) {
|
|
167
|
+
if (!component.added && this.useLongestToken) {
|
|
168
|
+
let value = newTokens.slice(newPos, newPos + component.count);
|
|
169
|
+
value = value.map(function(value, i) {
|
|
170
|
+
const oldValue = oldTokens[oldPos + i];
|
|
171
|
+
return oldValue.length > value.length ? oldValue : value;
|
|
172
|
+
});
|
|
173
|
+
component.value = this.join(value);
|
|
174
|
+
} else component.value = this.join(newTokens.slice(newPos, newPos + component.count));
|
|
175
|
+
newPos += component.count;
|
|
176
|
+
if (!component.added) oldPos += component.count;
|
|
177
|
+
} else {
|
|
178
|
+
component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
|
|
179
|
+
oldPos += component.count;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return components;
|
|
183
|
+
}
|
|
184
|
+
};
|
|
185
|
+
//#endregion
|
|
186
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/character.js
|
|
187
|
+
var CharacterDiff = class extends Diff {};
|
|
188
|
+
new CharacterDiff();
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/util/string.js
|
|
191
|
+
function longestCommonPrefix(str1, str2) {
|
|
192
|
+
let i = 0;
|
|
193
|
+
for (; i < str1.length && i < str2.length; i++) if (str1[i] != str2[i]) return str1.slice(0, i);
|
|
194
|
+
return str1.slice(0, i);
|
|
195
|
+
}
|
|
196
|
+
function longestCommonSuffix(str1, str2) {
|
|
197
|
+
let i;
|
|
198
|
+
if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) return "";
|
|
199
|
+
for (i = 0; i < str1.length && i < str2.length; i++) if (str1[str1.length - (i + 1)] != str2[str2.length - (i + 1)]) return str1.slice(-i);
|
|
200
|
+
return str1.slice(-i);
|
|
201
|
+
}
|
|
202
|
+
function replacePrefix(string, oldPrefix, newPrefix) {
|
|
203
|
+
if (string.slice(0, oldPrefix.length) != oldPrefix) throw Error(`string ${JSON.stringify(string)} doesn't start with prefix ${JSON.stringify(oldPrefix)}; this is a bug`);
|
|
204
|
+
return newPrefix + string.slice(oldPrefix.length);
|
|
205
|
+
}
|
|
206
|
+
function replaceSuffix(string, oldSuffix, newSuffix) {
|
|
207
|
+
if (!oldSuffix) return string + newSuffix;
|
|
208
|
+
if (string.slice(-oldSuffix.length) != oldSuffix) throw Error(`string ${JSON.stringify(string)} doesn't end with suffix ${JSON.stringify(oldSuffix)}; this is a bug`);
|
|
209
|
+
return string.slice(0, -oldSuffix.length) + newSuffix;
|
|
210
|
+
}
|
|
211
|
+
function removePrefix(string, oldPrefix) {
|
|
212
|
+
return replacePrefix(string, oldPrefix, "");
|
|
213
|
+
}
|
|
214
|
+
function removeSuffix(string, oldSuffix) {
|
|
215
|
+
return replaceSuffix(string, oldSuffix, "");
|
|
216
|
+
}
|
|
217
|
+
function maximumOverlap(string1, string2) {
|
|
218
|
+
return string2.slice(0, overlapCount(string1, string2));
|
|
219
|
+
}
|
|
220
|
+
function overlapCount(a, b) {
|
|
221
|
+
let startA = 0;
|
|
222
|
+
if (a.length > b.length) startA = a.length - b.length;
|
|
223
|
+
let endB = b.length;
|
|
224
|
+
if (a.length < b.length) endB = a.length;
|
|
225
|
+
const map = Array(endB);
|
|
226
|
+
let k = 0;
|
|
227
|
+
map[0] = 0;
|
|
228
|
+
for (let j = 1; j < endB; j++) {
|
|
229
|
+
if (b[j] == b[k]) map[j] = map[k];
|
|
230
|
+
else map[j] = k;
|
|
231
|
+
while (k > 0 && b[j] != b[k]) k = map[k];
|
|
232
|
+
if (b[j] == b[k]) k++;
|
|
233
|
+
}
|
|
234
|
+
k = 0;
|
|
235
|
+
for (let i = startA; i < a.length; i++) {
|
|
236
|
+
while (k > 0 && a[i] != b[k]) k = map[k];
|
|
237
|
+
if (a[i] == b[k]) k++;
|
|
238
|
+
}
|
|
239
|
+
return k;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Split a string into segments using a word segmenter, merging consecutive
|
|
243
|
+
* segments if they are both whitespace segments. Whitespace segments can
|
|
244
|
+
* appear adjacent to one another for two reasons:
|
|
245
|
+
* - newlines always get their own segment
|
|
246
|
+
* - where a diacritic is attached to a whitespace character in the text, the
|
|
247
|
+
* segment ends after the diacritic, so e.g. " \u0300 " becomes two segments.
|
|
248
|
+
* This function therefore runs the segmenter's .segment() method and then
|
|
249
|
+
* merges consecutive segments of whitespace into a single part.
|
|
250
|
+
*/
|
|
251
|
+
function segment(string, segmenter) {
|
|
252
|
+
const parts = [];
|
|
253
|
+
for (const segmentObj of Array.from(segmenter.segment(string))) {
|
|
254
|
+
const segment = segmentObj.segment;
|
|
255
|
+
if (parts.length && /\s/.test(parts[parts.length - 1]) && /\s/.test(segment)) parts[parts.length - 1] += segment;
|
|
256
|
+
else parts.push(segment);
|
|
257
|
+
}
|
|
258
|
+
return parts;
|
|
259
|
+
}
|
|
260
|
+
function trailingWs(string, segmenter) {
|
|
261
|
+
if (segmenter) return leadingAndTrailingWs(string, segmenter)[1];
|
|
262
|
+
let i;
|
|
263
|
+
for (i = string.length - 1; i >= 0; i--) if (!string[i].match(/\s/)) break;
|
|
264
|
+
return string.substring(i + 1);
|
|
265
|
+
}
|
|
266
|
+
function leadingWs(string, segmenter) {
|
|
267
|
+
if (segmenter) return leadingAndTrailingWs(string, segmenter)[0];
|
|
268
|
+
const match = string.match(/^\s*/);
|
|
269
|
+
return match ? match[0] : "";
|
|
270
|
+
}
|
|
271
|
+
function leadingAndTrailingWs(string, segmenter) {
|
|
272
|
+
if (!segmenter) return [leadingWs(string), trailingWs(string)];
|
|
273
|
+
if (segmenter.resolvedOptions().granularity != "word") throw new Error("The segmenter passed must have a granularity of \"word\"");
|
|
274
|
+
const segments = segment(string, segmenter);
|
|
275
|
+
const firstSeg = segments[0];
|
|
276
|
+
const lastSeg = segments[segments.length - 1];
|
|
277
|
+
return [/\s/.test(firstSeg) ? firstSeg : "", /\s/.test(lastSeg) ? lastSeg : ""];
|
|
278
|
+
}
|
|
279
|
+
//#endregion
|
|
280
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/word.js
|
|
281
|
+
const extendedWordChars = "a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}";
|
|
282
|
+
const tokenizeIncludingWhitespace = new RegExp(`[${extendedWordChars}]+|\\s+|[^${extendedWordChars}]`, "ug");
|
|
283
|
+
var WordDiff = class extends Diff {
|
|
284
|
+
equals(left, right, options) {
|
|
285
|
+
if (options.ignoreCase) {
|
|
286
|
+
left = left.toLowerCase();
|
|
287
|
+
right = right.toLowerCase();
|
|
288
|
+
}
|
|
289
|
+
return left.trim() === right.trim();
|
|
290
|
+
}
|
|
291
|
+
tokenize(value, options = {}) {
|
|
292
|
+
let parts;
|
|
293
|
+
if (options.intlSegmenter) {
|
|
294
|
+
const segmenter = options.intlSegmenter;
|
|
295
|
+
if (segmenter.resolvedOptions().granularity != "word") throw new Error("The segmenter passed must have a granularity of \"word\"");
|
|
296
|
+
parts = segment(value, segmenter);
|
|
297
|
+
} else parts = value.match(tokenizeIncludingWhitespace) || [];
|
|
298
|
+
const tokens = [];
|
|
299
|
+
let prevPart = null;
|
|
300
|
+
parts.forEach((part) => {
|
|
301
|
+
if (/\s/.test(part)) {
|
|
302
|
+
if (prevPart == null) tokens.push(part);
|
|
303
|
+
else tokens.push(tokens.pop() + part);
|
|
304
|
+
} else if (prevPart != null && /\s/.test(prevPart)) {
|
|
305
|
+
if (tokens[tokens.length - 1] == prevPart) tokens.push(tokens.pop() + part);
|
|
306
|
+
else tokens.push(prevPart + part);
|
|
307
|
+
} else tokens.push(part);
|
|
308
|
+
prevPart = part;
|
|
309
|
+
});
|
|
310
|
+
return tokens;
|
|
311
|
+
}
|
|
312
|
+
join(tokens) {
|
|
313
|
+
return tokens.map((token, i) => {
|
|
314
|
+
if (i == 0) return token;
|
|
315
|
+
else return token.replace(/^\s+/, "");
|
|
316
|
+
}).join("");
|
|
317
|
+
}
|
|
318
|
+
postProcess(changes, options) {
|
|
319
|
+
if (!changes || options.oneChangePerToken) return changes;
|
|
320
|
+
let lastKeep = null;
|
|
321
|
+
let insertion = null;
|
|
322
|
+
let deletion = null;
|
|
323
|
+
changes.forEach((change) => {
|
|
324
|
+
if (change.added) insertion = change;
|
|
325
|
+
else if (change.removed) deletion = change;
|
|
326
|
+
else {
|
|
327
|
+
if (insertion || deletion) dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, change, options.intlSegmenter);
|
|
328
|
+
lastKeep = change;
|
|
329
|
+
insertion = null;
|
|
330
|
+
deletion = null;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
if (insertion || deletion) dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, null, options.intlSegmenter);
|
|
334
|
+
return changes;
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
new WordDiff();
|
|
338
|
+
function dedupeWhitespaceInChangeObjects(startKeep, deletion, insertion, endKeep, segmenter) {
|
|
339
|
+
if (deletion && insertion) {
|
|
340
|
+
const [oldWsPrefix, oldWsSuffix] = leadingAndTrailingWs(deletion.value, segmenter);
|
|
341
|
+
const [newWsPrefix, newWsSuffix] = leadingAndTrailingWs(insertion.value, segmenter);
|
|
342
|
+
if (startKeep) {
|
|
343
|
+
const commonWsPrefix = longestCommonPrefix(oldWsPrefix, newWsPrefix);
|
|
344
|
+
startKeep.value = replaceSuffix(startKeep.value, newWsPrefix, commonWsPrefix);
|
|
345
|
+
deletion.value = removePrefix(deletion.value, commonWsPrefix);
|
|
346
|
+
insertion.value = removePrefix(insertion.value, commonWsPrefix);
|
|
347
|
+
}
|
|
348
|
+
if (endKeep) {
|
|
349
|
+
const commonWsSuffix = longestCommonSuffix(oldWsSuffix, newWsSuffix);
|
|
350
|
+
endKeep.value = replacePrefix(endKeep.value, newWsSuffix, commonWsSuffix);
|
|
351
|
+
deletion.value = removeSuffix(deletion.value, commonWsSuffix);
|
|
352
|
+
insertion.value = removeSuffix(insertion.value, commonWsSuffix);
|
|
353
|
+
}
|
|
354
|
+
} else if (insertion) {
|
|
355
|
+
if (startKeep) {
|
|
356
|
+
const ws = leadingWs(insertion.value, segmenter);
|
|
357
|
+
insertion.value = insertion.value.substring(ws.length);
|
|
358
|
+
}
|
|
359
|
+
if (endKeep) {
|
|
360
|
+
const ws = leadingWs(endKeep.value, segmenter);
|
|
361
|
+
endKeep.value = endKeep.value.substring(ws.length);
|
|
362
|
+
}
|
|
363
|
+
} else if (startKeep && endKeep) {
|
|
364
|
+
const newWsFull = leadingWs(endKeep.value, segmenter), [delWsStart, delWsEnd] = leadingAndTrailingWs(deletion.value, segmenter);
|
|
365
|
+
const newWsStart = longestCommonPrefix(newWsFull, delWsStart);
|
|
366
|
+
deletion.value = removePrefix(deletion.value, newWsStart);
|
|
367
|
+
const newWsEnd = longestCommonSuffix(removePrefix(newWsFull, newWsStart), delWsEnd);
|
|
368
|
+
deletion.value = removeSuffix(deletion.value, newWsEnd);
|
|
369
|
+
endKeep.value = replacePrefix(endKeep.value, newWsFull, newWsEnd);
|
|
370
|
+
startKeep.value = replaceSuffix(startKeep.value, newWsFull, newWsFull.slice(0, newWsFull.length - newWsEnd.length));
|
|
371
|
+
} else if (endKeep) {
|
|
372
|
+
const endKeepWsPrefix = leadingWs(endKeep.value, segmenter);
|
|
373
|
+
const overlap = maximumOverlap(trailingWs(deletion.value, segmenter), endKeepWsPrefix);
|
|
374
|
+
deletion.value = removeSuffix(deletion.value, overlap);
|
|
375
|
+
} else if (startKeep) {
|
|
376
|
+
const overlap = maximumOverlap(trailingWs(startKeep.value, segmenter), leadingWs(deletion.value, segmenter));
|
|
377
|
+
deletion.value = removePrefix(deletion.value, overlap);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
var WordsWithSpaceDiff = class extends Diff {
|
|
381
|
+
tokenize(value) {
|
|
382
|
+
const regex = new RegExp(`(\\r?\\n)|[${extendedWordChars}]+|[^\\S\\n\\r]+|[^${extendedWordChars}]`, "ug");
|
|
383
|
+
return value.match(regex) || [];
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
new WordsWithSpaceDiff();
|
|
387
|
+
//#endregion
|
|
388
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/line.js
|
|
389
|
+
var LineDiff = class extends Diff {
|
|
390
|
+
constructor() {
|
|
391
|
+
super(...arguments);
|
|
392
|
+
this.tokenize = tokenize;
|
|
393
|
+
}
|
|
394
|
+
equals(left, right, options) {
|
|
395
|
+
if (options.ignoreWhitespace) {
|
|
396
|
+
if (!options.newlineIsToken || !left.includes("\n")) left = left.trim();
|
|
397
|
+
if (!options.newlineIsToken || !right.includes("\n")) right = right.trim();
|
|
398
|
+
} else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
|
|
399
|
+
if (left.endsWith("\n")) left = left.slice(0, -1);
|
|
400
|
+
if (right.endsWith("\n")) right = right.slice(0, -1);
|
|
401
|
+
}
|
|
402
|
+
return super.equals(left, right, options);
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
const lineDiff = new LineDiff();
|
|
406
|
+
function diffLines(oldStr, newStr, options) {
|
|
407
|
+
return lineDiff.diff(oldStr, newStr, options);
|
|
408
|
+
}
|
|
409
|
+
function tokenize(value, options) {
|
|
410
|
+
if (options.stripTrailingCr) value = value.replace(/\r\n/g, "\n");
|
|
411
|
+
const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
|
|
412
|
+
if (!linesAndNewlines[linesAndNewlines.length - 1]) linesAndNewlines.pop();
|
|
413
|
+
for (let i = 0; i < linesAndNewlines.length; i++) {
|
|
414
|
+
const line = linesAndNewlines[i];
|
|
415
|
+
if (i % 2 && !options.newlineIsToken) retLines[retLines.length - 1] += line;
|
|
416
|
+
else retLines.push(line);
|
|
417
|
+
}
|
|
418
|
+
return retLines;
|
|
419
|
+
}
|
|
420
|
+
//#endregion
|
|
421
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/sentence.js
|
|
422
|
+
function isSentenceEndPunct(char) {
|
|
423
|
+
return char == "." || char == "!" || char == "?";
|
|
424
|
+
}
|
|
425
|
+
var SentenceDiff = class extends Diff {
|
|
426
|
+
tokenize(value) {
|
|
427
|
+
var _a;
|
|
428
|
+
const result = [];
|
|
429
|
+
let tokenStartI = 0;
|
|
430
|
+
for (let i = 0; i < value.length; i++) {
|
|
431
|
+
if (i == value.length - 1) {
|
|
432
|
+
result.push(value.slice(tokenStartI));
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
if (isSentenceEndPunct(value[i]) && value[i + 1].match(/\s/)) {
|
|
436
|
+
result.push(value.slice(tokenStartI, i + 1));
|
|
437
|
+
i = tokenStartI = i + 1;
|
|
438
|
+
while ((_a = value[i + 1]) === null || _a === void 0 ? void 0 : _a.match(/\s/)) i++;
|
|
439
|
+
result.push(value.slice(tokenStartI, i + 1));
|
|
440
|
+
tokenStartI = i + 1;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
return result;
|
|
444
|
+
}
|
|
445
|
+
};
|
|
446
|
+
new SentenceDiff();
|
|
447
|
+
//#endregion
|
|
448
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/css.js
|
|
449
|
+
var CssDiff = class extends Diff {
|
|
450
|
+
tokenize(value) {
|
|
451
|
+
return value.split(/([{}:;,]|\s+)/);
|
|
452
|
+
}
|
|
453
|
+
};
|
|
454
|
+
new CssDiff();
|
|
455
|
+
//#endregion
|
|
456
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/json.js
|
|
457
|
+
var JsonDiff = class extends Diff {
|
|
458
|
+
constructor() {
|
|
459
|
+
super(...arguments);
|
|
460
|
+
this.tokenize = tokenize;
|
|
461
|
+
}
|
|
462
|
+
get useLongestToken() {
|
|
463
|
+
return true;
|
|
464
|
+
}
|
|
465
|
+
castInput(value, options) {
|
|
466
|
+
const { undefinedReplacement, stringifyReplacer = (k, v) => typeof v === "undefined" ? undefinedReplacement : v } = options;
|
|
467
|
+
return typeof value === "string" ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), null, " ");
|
|
468
|
+
}
|
|
469
|
+
equals(left, right, options) {
|
|
470
|
+
return super.equals(left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"), options);
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
new JsonDiff();
|
|
474
|
+
function canonicalize(obj, stack, replacementStack, replacer, key) {
|
|
475
|
+
stack = stack || [];
|
|
476
|
+
replacementStack = replacementStack || [];
|
|
477
|
+
if (replacer) obj = replacer(key === void 0 ? "" : key, obj);
|
|
478
|
+
let i = 0;
|
|
479
|
+
for (; i < stack.length; i += 1) if (stack[i] === obj) return replacementStack[i];
|
|
480
|
+
let canonicalizedObj;
|
|
481
|
+
if ("[object Array]" === Object.prototype.toString.call(obj)) {
|
|
482
|
+
stack.push(obj);
|
|
483
|
+
canonicalizedObj = new Array(obj.length);
|
|
484
|
+
replacementStack.push(canonicalizedObj);
|
|
485
|
+
for (i = 0; i < obj.length; i += 1) canonicalizedObj[i] = canonicalize(obj[i], stack, replacementStack, replacer, String(i));
|
|
486
|
+
stack.pop();
|
|
487
|
+
replacementStack.pop();
|
|
488
|
+
return canonicalizedObj;
|
|
489
|
+
}
|
|
490
|
+
if (obj && obj.toJSON) obj = obj.toJSON();
|
|
491
|
+
if (typeof obj === "object" && obj !== null) {
|
|
492
|
+
stack.push(obj);
|
|
493
|
+
canonicalizedObj = {};
|
|
494
|
+
replacementStack.push(canonicalizedObj);
|
|
495
|
+
const sortedKeys = [];
|
|
496
|
+
let key;
|
|
497
|
+
for (key in obj)
|
|
498
|
+
/* istanbul ignore else */
|
|
499
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) sortedKeys.push(key);
|
|
500
|
+
sortedKeys.sort();
|
|
501
|
+
for (i = 0; i < sortedKeys.length; i += 1) {
|
|
502
|
+
key = sortedKeys[i];
|
|
503
|
+
canonicalizedObj[key] = canonicalize(obj[key], stack, replacementStack, replacer, key);
|
|
504
|
+
}
|
|
505
|
+
stack.pop();
|
|
506
|
+
replacementStack.pop();
|
|
507
|
+
} else canonicalizedObj = obj;
|
|
508
|
+
return canonicalizedObj;
|
|
509
|
+
}
|
|
510
|
+
//#endregion
|
|
511
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/array.js
|
|
512
|
+
var ArrayDiff = class extends Diff {
|
|
513
|
+
tokenize(value) {
|
|
514
|
+
return value.slice();
|
|
515
|
+
}
|
|
516
|
+
join(value) {
|
|
517
|
+
return value;
|
|
518
|
+
}
|
|
519
|
+
removeEmpty(value) {
|
|
520
|
+
return value;
|
|
521
|
+
}
|
|
522
|
+
};
|
|
523
|
+
new ArrayDiff();
|
|
524
|
+
//#endregion
|
|
525
|
+
//#region ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/patch/create.js
|
|
526
|
+
/**
|
|
527
|
+
* Returns true if the filename contains characters that require C-style
|
|
528
|
+
* quoting (as used by Git and GNU diffutils in diff output).
|
|
529
|
+
*/
|
|
530
|
+
function needsQuoting(s) {
|
|
531
|
+
for (let i = 0; i < s.length; i++) if (s[i] < " " || s[i] > "~" || s[i] === "\"" || s[i] === "\\") return true;
|
|
532
|
+
return false;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* C-style quotes a filename, encoding special characters as escape sequences
|
|
536
|
+
* and non-ASCII bytes as octal escapes. This is the inverse of
|
|
537
|
+
* `parseQuotedFileName` in parse.ts.
|
|
538
|
+
*
|
|
539
|
+
* Non-ASCII bytes are encoded as UTF-8 before being emitted as octal escapes.
|
|
540
|
+
* This matches the behaviour of both Git and GNU diffutils, which always emit
|
|
541
|
+
* UTF-8 octal escapes regardless of the underlying filesystem encoding (e.g.
|
|
542
|
+
* Git for Windows converts from NTFS's UTF-16 to UTF-8 internally).
|
|
543
|
+
*
|
|
544
|
+
* If the filename doesn't need quoting, returns it as-is.
|
|
545
|
+
*/
|
|
546
|
+
function quoteFileNameIfNeeded(s) {
|
|
547
|
+
if (!needsQuoting(s)) return s;
|
|
548
|
+
let result = "\"";
|
|
549
|
+
const bytes = new TextEncoder().encode(s);
|
|
550
|
+
let i = 0;
|
|
551
|
+
while (i < bytes.length) {
|
|
552
|
+
const b = bytes[i];
|
|
553
|
+
if (b === 7) result += "\\a";
|
|
554
|
+
else if (b === 8) result += "\\b";
|
|
555
|
+
else if (b === 9) result += "\\t";
|
|
556
|
+
else if (b === 10) result += "\\n";
|
|
557
|
+
else if (b === 11) result += "\\v";
|
|
558
|
+
else if (b === 12) result += "\\f";
|
|
559
|
+
else if (b === 13) result += "\\r";
|
|
560
|
+
else if (b === 34) result += "\\\"";
|
|
561
|
+
else if (b === 92) result += "\\\\";
|
|
562
|
+
else if (b >= 32 && b <= 126) result += String.fromCharCode(b);
|
|
563
|
+
else result += "\\" + b.toString(8).padStart(3, "0");
|
|
564
|
+
i++;
|
|
565
|
+
}
|
|
566
|
+
result += "\"";
|
|
567
|
+
return result;
|
|
568
|
+
}
|
|
569
|
+
const INCLUDE_HEADERS = {
|
|
570
|
+
includeIndex: true,
|
|
571
|
+
includeUnderline: true,
|
|
572
|
+
includeFileHeaders: true
|
|
573
|
+
};
|
|
574
|
+
function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
|
|
575
|
+
let optionsObj;
|
|
576
|
+
if (!options) optionsObj = {};
|
|
577
|
+
else if (typeof options === "function") optionsObj = { callback: options };
|
|
578
|
+
else optionsObj = options;
|
|
579
|
+
if (typeof optionsObj.context === "undefined") optionsObj.context = 4;
|
|
580
|
+
const context = optionsObj.context;
|
|
581
|
+
if (optionsObj.newlineIsToken) throw new Error("newlineIsToken may not be used with patch-generation functions, only with diffing functions");
|
|
582
|
+
if (!optionsObj.callback) return diffLinesResultToPatch(diffLines(oldStr, newStr, optionsObj));
|
|
583
|
+
else {
|
|
584
|
+
const { callback } = optionsObj;
|
|
585
|
+
diffLines(oldStr, newStr, Object.assign(Object.assign({}, optionsObj), { callback: (diff) => {
|
|
586
|
+
const patch = diffLinesResultToPatch(diff);
|
|
587
|
+
callback(patch);
|
|
588
|
+
} }));
|
|
589
|
+
}
|
|
590
|
+
function diffLinesResultToPatch(diff) {
|
|
591
|
+
if (!diff) return;
|
|
592
|
+
diff.push({
|
|
593
|
+
value: "",
|
|
594
|
+
lines: []
|
|
595
|
+
});
|
|
596
|
+
function contextLines(lines) {
|
|
597
|
+
return lines.map(function(entry) {
|
|
598
|
+
return " " + entry;
|
|
599
|
+
});
|
|
600
|
+
}
|
|
601
|
+
const hunks = [];
|
|
602
|
+
let oldRangeStart = 0, newRangeStart = 0, curRange = [], oldLine = 1, newLine = 1;
|
|
603
|
+
for (let i = 0; i < diff.length; i++) {
|
|
604
|
+
const current = diff[i], lines = current.lines || splitLines(current.value);
|
|
605
|
+
current.lines = lines;
|
|
606
|
+
if (current.added || current.removed) {
|
|
607
|
+
if (!oldRangeStart) {
|
|
608
|
+
const prev = diff[i - 1];
|
|
609
|
+
oldRangeStart = oldLine;
|
|
610
|
+
newRangeStart = newLine;
|
|
611
|
+
if (prev) {
|
|
612
|
+
curRange = context > 0 ? contextLines(prev.lines.slice(-context)) : [];
|
|
613
|
+
oldRangeStart -= curRange.length;
|
|
614
|
+
newRangeStart -= curRange.length;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
for (const line of lines) curRange.push((current.added ? "+" : "-") + line);
|
|
618
|
+
if (current.added) newLine += lines.length;
|
|
619
|
+
else oldLine += lines.length;
|
|
620
|
+
} else {
|
|
621
|
+
if (oldRangeStart) {
|
|
622
|
+
if (lines.length <= context * 2 && i < diff.length - 2) for (const line of contextLines(lines)) curRange.push(line);
|
|
623
|
+
else {
|
|
624
|
+
const contextSize = Math.min(lines.length, context);
|
|
625
|
+
for (const line of contextLines(lines.slice(0, contextSize))) curRange.push(line);
|
|
626
|
+
const hunk = {
|
|
627
|
+
oldStart: oldRangeStart,
|
|
628
|
+
oldLines: oldLine - oldRangeStart + contextSize,
|
|
629
|
+
newStart: newRangeStart,
|
|
630
|
+
newLines: newLine - newRangeStart + contextSize,
|
|
631
|
+
lines: curRange
|
|
632
|
+
};
|
|
633
|
+
hunks.push(hunk);
|
|
634
|
+
oldRangeStart = 0;
|
|
635
|
+
newRangeStart = 0;
|
|
636
|
+
curRange = [];
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
oldLine += lines.length;
|
|
640
|
+
newLine += lines.length;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
for (const hunk of hunks) for (let i = 0; i < hunk.lines.length; i++) if (hunk.lines[i].endsWith("\n")) hunk.lines[i] = hunk.lines[i].slice(0, -1);
|
|
644
|
+
else {
|
|
645
|
+
hunk.lines.splice(i + 1, 0, "\");
|
|
646
|
+
i++;
|
|
647
|
+
}
|
|
648
|
+
return {
|
|
649
|
+
oldFileName,
|
|
650
|
+
newFileName,
|
|
651
|
+
oldHeader,
|
|
652
|
+
newHeader,
|
|
653
|
+
hunks
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
/**
|
|
658
|
+
* creates a unified diff patch.
|
|
659
|
+
*
|
|
660
|
+
* @param patch either a single structured patch object (as returned by `structuredPatch`) or an
|
|
661
|
+
* array of them (as returned by `parsePatch`).
|
|
662
|
+
* @param headerOptions behaves the same as the `headerOptions` option of `createTwoFilesPatch`.
|
|
663
|
+
* Ignored for patches where `isGit` is `true`.
|
|
664
|
+
*
|
|
665
|
+
* When a patch has `isGit: true`, `formatPatch` output is changed to more closely match Git's
|
|
666
|
+
* output: it emits a `diff --git` header, emits Git extended headers as appropriate based on
|
|
667
|
+
* properties like `isRename`, `isCreate`, `newMode`, etc, and will omit `---`/`+++` file
|
|
668
|
+
* headers for patches with no hunks (e.g. renames without content changes).
|
|
669
|
+
*/
|
|
670
|
+
function formatPatch(patch, headerOptions) {
|
|
671
|
+
var _a, _b, _c, _d, _e, _f;
|
|
672
|
+
if (!headerOptions) headerOptions = INCLUDE_HEADERS;
|
|
673
|
+
if (Array.isArray(patch)) {
|
|
674
|
+
if (patch.length > 1 && !headerOptions.includeFileHeaders && !patch.every((p) => p.isGit)) throw new Error("Cannot omit file headers on a multi-file patch. (The result would be unparseable; how would a tool trying to apply the patch know which changes are to which file?)");
|
|
675
|
+
return patch.map((p) => formatPatch(p, headerOptions)).join("\n");
|
|
676
|
+
}
|
|
677
|
+
const ret = [];
|
|
678
|
+
if (patch.isGit) {
|
|
679
|
+
headerOptions = INCLUDE_HEADERS;
|
|
680
|
+
if (!patch.oldFileName) throw new Error("oldFileName must be specified for Git patches");
|
|
681
|
+
if (!patch.newFileName) throw new Error("newFileName must be specified for Git patches");
|
|
682
|
+
let gitOldName = patch.oldFileName;
|
|
683
|
+
let gitNewName = patch.newFileName;
|
|
684
|
+
if (patch.isCreate && gitOldName === "/dev/null") gitOldName = gitNewName.replace(/^b\//, "a/");
|
|
685
|
+
else if (patch.isDelete && gitNewName === "/dev/null") gitNewName = gitOldName.replace(/^a\//, "b/");
|
|
686
|
+
ret.push("diff --git " + quoteFileNameIfNeeded(gitOldName) + " " + quoteFileNameIfNeeded(gitNewName));
|
|
687
|
+
if (patch.isDelete) ret.push("deleted file mode " + ((_a = patch.oldMode) !== null && _a !== void 0 ? _a : "100644"));
|
|
688
|
+
if (patch.isCreate) ret.push("new file mode " + ((_b = patch.newMode) !== null && _b !== void 0 ? _b : "100644"));
|
|
689
|
+
if (patch.oldMode && patch.newMode && !patch.isDelete && !patch.isCreate) {
|
|
690
|
+
ret.push("old mode " + patch.oldMode);
|
|
691
|
+
ret.push("new mode " + patch.newMode);
|
|
692
|
+
}
|
|
693
|
+
if (patch.isRename) {
|
|
694
|
+
ret.push("rename from " + quoteFileNameIfNeeded(((_c = patch.oldFileName) !== null && _c !== void 0 ? _c : "").replace(/^a\//, "")));
|
|
695
|
+
ret.push("rename to " + quoteFileNameIfNeeded(((_d = patch.newFileName) !== null && _d !== void 0 ? _d : "").replace(/^b\//, "")));
|
|
696
|
+
}
|
|
697
|
+
if (patch.isCopy) {
|
|
698
|
+
ret.push("copy from " + quoteFileNameIfNeeded(((_e = patch.oldFileName) !== null && _e !== void 0 ? _e : "").replace(/^a\//, "")));
|
|
699
|
+
ret.push("copy to " + quoteFileNameIfNeeded(((_f = patch.newFileName) !== null && _f !== void 0 ? _f : "").replace(/^b\//, "")));
|
|
700
|
+
}
|
|
701
|
+
} else {
|
|
702
|
+
if (headerOptions.includeIndex && patch.oldFileName == patch.newFileName && patch.oldFileName !== void 0) ret.push("Index: " + patch.oldFileName);
|
|
703
|
+
if (headerOptions.includeUnderline) ret.push("===================================================================");
|
|
704
|
+
}
|
|
705
|
+
const hasHunks = patch.hunks.length > 0;
|
|
706
|
+
if (headerOptions.includeFileHeaders && patch.oldFileName !== void 0 && patch.newFileName !== void 0 && (!patch.isGit || hasHunks)) {
|
|
707
|
+
ret.push("--- " + quoteFileNameIfNeeded(patch.oldFileName) + (patch.oldHeader ? " " + patch.oldHeader : ""));
|
|
708
|
+
ret.push("+++ " + quoteFileNameIfNeeded(patch.newFileName) + (patch.newHeader ? " " + patch.newHeader : ""));
|
|
709
|
+
}
|
|
710
|
+
for (let i = 0; i < patch.hunks.length; i++) {
|
|
711
|
+
const hunk = patch.hunks[i];
|
|
712
|
+
const oldStart = hunk.oldLines === 0 ? hunk.oldStart - 1 : hunk.oldStart;
|
|
713
|
+
const newStart = hunk.newLines === 0 ? hunk.newStart - 1 : hunk.newStart;
|
|
714
|
+
ret.push("@@ -" + oldStart + "," + hunk.oldLines + " +" + newStart + "," + hunk.newLines + " @@");
|
|
715
|
+
for (const line of hunk.lines) ret.push(line);
|
|
716
|
+
}
|
|
717
|
+
return ret.join("\n") + "\n";
|
|
718
|
+
}
|
|
719
|
+
function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
|
|
720
|
+
if (typeof options === "function") options = { callback: options };
|
|
721
|
+
if (!(options === null || options === void 0 ? void 0 : options.callback)) {
|
|
722
|
+
const patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options);
|
|
723
|
+
if (!patchObj) return;
|
|
724
|
+
return formatPatch(patchObj, options === null || options === void 0 ? void 0 : options.headerOptions);
|
|
725
|
+
} else {
|
|
726
|
+
const { callback } = options;
|
|
727
|
+
structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, Object.assign(Object.assign({}, options), { callback: (patchObj) => {
|
|
728
|
+
if (!patchObj) callback(void 0);
|
|
729
|
+
else callback(formatPatch(patchObj, options.headerOptions));
|
|
730
|
+
} }));
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Split `text` into an array of lines, including the trailing newline character (where present)
|
|
735
|
+
*/
|
|
736
|
+
function splitLines(text) {
|
|
737
|
+
const hasTrailingNl = text.endsWith("\n");
|
|
738
|
+
const result = text.split("\n").map((line) => line + "\n");
|
|
739
|
+
if (hasTrailingNl) result.pop();
|
|
740
|
+
else result.push(result.pop().slice(0, -1));
|
|
741
|
+
return result;
|
|
742
|
+
}
|
|
743
|
+
function paintLine(line, paint) {
|
|
744
|
+
if (line.startsWith("---") || line.startsWith("+++")) return paint("bold", line);
|
|
745
|
+
if (line.startsWith("@@")) return paint("cyan", line);
|
|
746
|
+
if (line.startsWith("+")) return paint("green", line);
|
|
747
|
+
if (line.startsWith("-")) return paint("red", line);
|
|
748
|
+
return line;
|
|
749
|
+
}
|
|
750
|
+
/** A unified diff from the file on disk (`current`, missing when `undefined`) to `next`, capped at `DIFF_LINES`. */
|
|
751
|
+
function fileDiff(path, current, next, paint = plain) {
|
|
752
|
+
const lines = createTwoFilesPatch(path, path, current ?? "", next, current === void 0 ? "missing" : "on disk", "generated", { context: 2 }).split("\n").filter((line) => line !== "" && !line.startsWith("=====") && !line.startsWith("Index:"));
|
|
753
|
+
const shown = lines.slice(0, 40).map((line) => paintLine(line, paint));
|
|
754
|
+
const hidden = lines.length - shown.length;
|
|
755
|
+
return [...shown, ...hidden > 0 ? [paint("dim", `... ${hidden} more diff lines`)] : []].join("\n");
|
|
756
|
+
}
|
|
757
|
+
//#endregion
|
|
758
|
+
//#region src/cli/permdock.ts
|
|
759
|
+
const PERMDOCK_CONFIGS = [
|
|
760
|
+
"permdock.config.ts",
|
|
761
|
+
"permdock.config.mts",
|
|
762
|
+
"permdock.config.js",
|
|
763
|
+
"permdock.config.mjs"
|
|
764
|
+
];
|
|
765
|
+
/** The PermDock config file in `root`, if there is one. */
|
|
766
|
+
function permdockConfig(root) {
|
|
767
|
+
return PERMDOCK_CONFIGS.find((file) => existsSync(resolve(root, file)));
|
|
768
|
+
}
|
|
769
|
+
const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
770
|
+
const isString = (value) => typeof value === "string";
|
|
771
|
+
const strings = (value) => Array.isArray(value) ? value.filter(isString) : [];
|
|
772
|
+
const column = (value) => isRecord(value) && isString(value["column"]) ? { column: value["column"] } : void 0;
|
|
773
|
+
function manifestValue(value, accept) {
|
|
774
|
+
if (!isRecord(value)) return void 0;
|
|
775
|
+
if (isString(value["column"])) return { column: value["column"] };
|
|
776
|
+
return accept(value["value"]) ? { value: value["value"] } : void 0;
|
|
777
|
+
}
|
|
778
|
+
const roleValue = (value) => isString(value) || Array.isArray(value) && value.every(isString);
|
|
779
|
+
function membership(value) {
|
|
780
|
+
if (!isRecord(value) || !isString(value["table"])) return void 0;
|
|
781
|
+
const user = column(value["user"]);
|
|
782
|
+
const id = column(value["id"]);
|
|
783
|
+
const scope = manifestValue(value["scope"], isString);
|
|
784
|
+
if (!user || !id || !scope) return void 0;
|
|
785
|
+
const role = manifestValue(value["role"], roleValue);
|
|
786
|
+
const expiresAt = column(value["expiresAt"]);
|
|
787
|
+
return {
|
|
788
|
+
table: value["table"],
|
|
789
|
+
user,
|
|
790
|
+
scope,
|
|
791
|
+
id,
|
|
792
|
+
...role ? { role } : {},
|
|
793
|
+
...expiresAt ? { expiresAt } : {},
|
|
794
|
+
columns: strings(value["columns"])
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
/** Reads a parsed manifest; throws with the reason when it isn't version 1. */
|
|
798
|
+
function parseManifest(json) {
|
|
799
|
+
if (!isRecord(json)) throw new TypeError("not a JSON object");
|
|
800
|
+
if (json["version"] !== 1) throw new TypeError(`version ${String(json["version"])} is not supported (this release reads version 1)`);
|
|
801
|
+
const hook = json["hook"];
|
|
802
|
+
const rls = json["rls"];
|
|
803
|
+
const budget = isRecord(json["budget"]) ? json["budget"]["bytes"] : void 0;
|
|
804
|
+
return {
|
|
805
|
+
version: 1,
|
|
806
|
+
...typeof budget === "number" ? { budget } : {},
|
|
807
|
+
...isRecord(hook) && isString(hook["schema"]) && isString(hook["function"]) ? { hook: {
|
|
808
|
+
schema: hook["schema"],
|
|
809
|
+
function: hook["function"]
|
|
810
|
+
} } : {},
|
|
811
|
+
...isString(json["tenantClaim"]) ? { tenantClaim: json["tenantClaim"] } : {},
|
|
812
|
+
claims: (Array.isArray(json["claims"]) ? json["claims"] : []).flatMap((claim) => isRecord(claim) && isString(claim["name"]) && isString(claim["source"]) ? [{
|
|
813
|
+
name: claim["name"],
|
|
814
|
+
source: claim["source"]
|
|
815
|
+
}] : []),
|
|
816
|
+
memberships: (Array.isArray(json["memberships"]) ? json["memberships"] : []).flatMap((entry) => {
|
|
817
|
+
const parsed = membership(entry);
|
|
818
|
+
return parsed ? [parsed] : [];
|
|
819
|
+
}),
|
|
820
|
+
...isRecord(rls) && isString(rls["schema"]) ? { rls: {
|
|
821
|
+
schema: rls["schema"],
|
|
822
|
+
mode: rls["mode"] === "jwt" ? "jwt" : "database",
|
|
823
|
+
scopes: (Array.isArray(rls["scopes"]) ? rls["scopes"] : []).flatMap((scope) => isRecord(scope) && isString(scope["name"]) && isString(scope["type"]) ? [{
|
|
824
|
+
name: scope["name"],
|
|
825
|
+
type: scope["type"]
|
|
826
|
+
}] : []),
|
|
827
|
+
helpers: (Array.isArray(rls["helpers"]) ? rls["helpers"] : []).flatMap((helper) => isRecord(helper) && isString(helper["name"]) && isString(helper["args"]) && isString(helper["returns"]) ? [{
|
|
828
|
+
name: helper["name"],
|
|
829
|
+
args: helper["args"],
|
|
830
|
+
returns: helper["returns"],
|
|
831
|
+
execute: strings(helper["execute"])
|
|
832
|
+
}] : [])
|
|
833
|
+
} } : {},
|
|
834
|
+
decidingColumns: strings(json["decidingColumns"])
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
/** The keys of a parsed `permissions.catalog.json` whose entry has `rowConditions: true`. */
|
|
838
|
+
function rowConditionKeys(json) {
|
|
839
|
+
if (!isRecord(json) || !Array.isArray(json["permissions"])) throw new TypeError("has no permissions array");
|
|
840
|
+
const keys = /* @__PURE__ */ new Set();
|
|
841
|
+
for (const permission of json["permissions"]) if (isRecord(permission) && isString(permission["key"]) && permission["rowConditions"] === true) keys.add(permission["key"]);
|
|
842
|
+
return keys;
|
|
843
|
+
}
|
|
844
|
+
async function readJson(root, path) {
|
|
845
|
+
const absolute = resolve(root, path);
|
|
846
|
+
if (!existsSync(absolute)) return { missing: true };
|
|
847
|
+
try {
|
|
848
|
+
return { json: JSON.parse(await readFile(absolute, "utf8")) };
|
|
849
|
+
} catch (cause) {
|
|
850
|
+
return { problem: `${path}: ${cause instanceof Error ? cause.message : String(cause)}` };
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Reads PermDock's JSON outputs: the manifest `permdock supabase inspect
|
|
855
|
+
* --out` writes and the catalog `permdock catalog` writes. Nothing is
|
|
856
|
+
* imported from PermDock. Returns `undefined` when the project has neither a
|
|
857
|
+
* PermDock config nor a manifest.
|
|
858
|
+
*/
|
|
859
|
+
async function readPermdock(root, paths) {
|
|
860
|
+
const config = permdockConfig(root);
|
|
861
|
+
const problems = [];
|
|
862
|
+
const manifestFile = await readJson(root, paths.manifest);
|
|
863
|
+
let manifest;
|
|
864
|
+
if ("json" in manifestFile) try {
|
|
865
|
+
manifest = parseManifest(manifestFile.json);
|
|
866
|
+
} catch (cause) {
|
|
867
|
+
problems.push(`${paths.manifest}: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
868
|
+
}
|
|
869
|
+
else if ("problem" in manifestFile) problems.push(manifestFile.problem);
|
|
870
|
+
if (!config && !manifest && "missing" in manifestFile) return void 0;
|
|
871
|
+
const catalogFile = await readJson(root, paths.catalog);
|
|
872
|
+
let rowConditions;
|
|
873
|
+
if ("json" in catalogFile) try {
|
|
874
|
+
rowConditions = rowConditionKeys(catalogFile.json);
|
|
875
|
+
} catch (cause) {
|
|
876
|
+
problems.push(`${paths.catalog}: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
877
|
+
}
|
|
878
|
+
else if ("problem" in catalogFile) problems.push(catalogFile.problem);
|
|
879
|
+
return {
|
|
880
|
+
...config ? { config } : {},
|
|
881
|
+
manifestPath: paths.manifest,
|
|
882
|
+
...manifest ? { manifest } : {},
|
|
883
|
+
catalogPath: paths.catalog,
|
|
884
|
+
...rowConditions ? { rowConditions } : {},
|
|
885
|
+
problems
|
|
886
|
+
};
|
|
887
|
+
}
|
|
888
|
+
/** How findings name the PermDock project: its config file or its manifest. */
|
|
889
|
+
const permdockSource = (project) => project.config ?? project.manifestPath;
|
|
890
|
+
const HOOK_MARKER = /^--\s*permdock:hook\s+v(\d+)([^\n]*)$/m;
|
|
891
|
+
const GRANTS_MARKER = /^--\s*permdock:grants\s+v(\d+)([^\n]*)$/m;
|
|
892
|
+
function markerFields(rest) {
|
|
893
|
+
const fields = /* @__PURE__ */ new Map();
|
|
894
|
+
for (const match of rest.matchAll(/(\w+)=(\S*)/g)) fields.set(match[1], match[2]);
|
|
895
|
+
return fields;
|
|
896
|
+
}
|
|
897
|
+
/** The `-- permdock:hook v1 schema=... tenant=... budget=... claims=...` line PermDock's hook file starts with. */
|
|
898
|
+
function parseHookMarker(sql) {
|
|
899
|
+
const match = HOOK_MARKER.exec(sql);
|
|
900
|
+
if (!match) return void 0;
|
|
901
|
+
const fields = markerFields(match[2]);
|
|
902
|
+
const budget = Number(fields.get("budget"));
|
|
903
|
+
const schema = fields.get("schema");
|
|
904
|
+
const tenantClaim = fields.get("tenant");
|
|
905
|
+
return {
|
|
906
|
+
version: Number(match[1]),
|
|
907
|
+
...schema ? { schema } : {},
|
|
908
|
+
...tenantClaim ? { tenantClaim } : {},
|
|
909
|
+
...Number.isFinite(budget) && fields.has("budget") ? { budget } : {},
|
|
910
|
+
claims: (fields.get("claims") ?? "").split(",").filter(Boolean)
|
|
911
|
+
};
|
|
912
|
+
}
|
|
913
|
+
/** The `-- permdock:grants v1 schema=...` line of the migration `--grants-out` writes. */
|
|
914
|
+
function parseGrantsMarker(sql) {
|
|
915
|
+
const match = GRANTS_MARKER.exec(sql);
|
|
916
|
+
if (!match) return void 0;
|
|
917
|
+
const schema = markerFields(match[2]).get("schema");
|
|
918
|
+
return {
|
|
919
|
+
version: Number(match[1]),
|
|
920
|
+
...schema ? { schema } : {}
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
/**
|
|
924
|
+
* PermDock mode, when the manifest has an `rls` block and
|
|
925
|
+
* `entitlements.permdock` is not `false`: the scope must be one of the
|
|
926
|
+
* manifest's `rls.scopes`. Without a manifest the module keeps using `tenant`.
|
|
927
|
+
*/
|
|
928
|
+
function entitlementsMode(config, project) {
|
|
929
|
+
const setting = config.entitlements.permdock;
|
|
930
|
+
const rls = project?.manifest?.rls;
|
|
931
|
+
if (setting === false || !project?.manifest || !rls) return { kind: "tenant" };
|
|
932
|
+
if (!rls.scopes.some((scope) => scope.name === setting.scope)) return {
|
|
933
|
+
kind: "invalid",
|
|
934
|
+
problem: `entitlements.permdock.scope is "${setting.scope}", but ${project.manifestPath} has the scopes ${rls.scopes.map((scope) => scope.name).join(", ") || "(none)"}. Set entitlements.permdock: { scope } to one of them.`
|
|
935
|
+
};
|
|
936
|
+
return {
|
|
937
|
+
kind: "permdock",
|
|
938
|
+
permdock: {
|
|
939
|
+
schema: rls.schema,
|
|
940
|
+
scope: setting.scope,
|
|
941
|
+
memberships: project.manifest.memberships.map((source) => ({
|
|
942
|
+
table: source.table,
|
|
943
|
+
userColumn: source.user.column,
|
|
944
|
+
scope: source.scope,
|
|
945
|
+
idColumn: source.id.column
|
|
946
|
+
}))
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
/** The `member_<scope>_ids` helpers PermDock mode calls, as `schema.name`. */
|
|
951
|
+
const entitlementHelpers = (permdock) => [`${permdock.schema}.member_${permdock.scope}_ids`, `${permdock.schema}.member_${permdock.scope}_ids_for`];
|
|
952
|
+
//#endregion
|
|
953
|
+
//#region src/cli/read-sets.ts
|
|
954
|
+
/** Every read set exported by the modules in `config.readSets`. */
|
|
955
|
+
async function loadReadSets(config) {
|
|
956
|
+
const sets = [];
|
|
957
|
+
for (const entry of config.readSets) {
|
|
958
|
+
const loaded = await importModule(resolve(config.root, entry));
|
|
959
|
+
const found = Object.values(loaded).filter(isReadSet);
|
|
960
|
+
if (found.length === 0) throw new Error(`${entry} exports no read set (defineReadSet)`);
|
|
961
|
+
for (const set of found) if (!sets.includes(set)) sets.push(set);
|
|
962
|
+
}
|
|
963
|
+
return sets;
|
|
964
|
+
}
|
|
965
|
+
/** The compiled functions for `config.readSets`; empty when none are configured. */
|
|
966
|
+
async function compiledReadSets(config) {
|
|
967
|
+
if (config.readSets.length === 0) return [];
|
|
968
|
+
return compileReadSets(await loadReadSets(config));
|
|
969
|
+
}
|
|
970
|
+
//#endregion
|
|
971
|
+
export { parseHookMarker as a, readPermdock as c, parseGrantsMarker as i, fileDiff as l, entitlementHelpers as n, permdockConfig as o, entitlementsMode as r, permdockSource as s, compiledReadSets as t };
|