@payload-auth-link/migrate 0.2.0 → 0.3.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 CHANGED
@@ -47,4 +47,6 @@ Bun's module loader, which tolerates the directory imports
47
47
  payload-auth's dist uses.
48
48
 
49
49
  Peers: `payload` ^3.83.0 || 4.0.0-beta.0 (the import commands boot the
50
- app's own Payload instance; the doctor itself only reads).
50
+ app's own Payload instance; the doctor itself only reads),
51
+ `better-auth` >=1.7.6 <1.8.0, and `@payload-auth-link/next` ^0.3.1
52
+ (optional — only the codemod's emitted route handlers need it).
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AA6KA,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACxC,CAAA;AAED,iBAAe,IAAI,CACjB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,GAAE,OAAwB,EAC7B,GAAG,GAAE,OAAwB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAwFjB;AAiBD,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,CAAA"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAuLA,KAAK,OAAO,GAAG;IACb,QAAQ,CAAC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CACxC,CAAA;AAED,iBAAe,IAAI,CACjB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,GAAG,GAAE,OAAwB,EAC7B,GAAG,GAAE,OAAwB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAiLjB;AAiBD,OAAO,EAAE,IAAI,IAAI,OAAO,EAAE,CAAA"}
package/dist/cli.js CHANGED
@@ -11,6 +11,9 @@
11
11
  */
12
12
  import { runDoctor } from './doctor/run-doctor.js';
13
13
  import { runFinalize, runFromPayloadAuth, runRollback, runVerify, } from './importer/run-import.js';
14
+ import { applyCodemods } from './codemods.js';
15
+ import { readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
16
+ import { extname, join, relative } from 'node:path';
14
17
  function parseArgs(argv) {
15
18
  const positional = [];
16
19
  const flags = new Map();
@@ -47,6 +50,9 @@ function usage() {
47
50
 
48
51
  Commands:
49
52
  doctor --config ./src/payload.config.ts [--src ./src] [--json] [--database-url URL]
53
+ export --database-url URL [--out file.jsonl]
54
+ (lossless JSONL of every auth table — the off-ramp, #58)
55
+ codemod --src ./src [--write]
50
56
  from-payload-auth --config ./src/payload.config.ts [--apply] [--sessions=carry|drop]
51
57
  [--manifest ./payload-auth-link-migration.json] [--database-url URL] [--json]
52
58
  verify --config ./src/payload.config.ts [--database-url URL] [--json]
@@ -66,6 +72,10 @@ Commands:
66
72
  rollback undoes exactly the manifest; finalize marks it read-only
67
73
  so the legacy tables may be dropped later, in their own migration.
68
74
 
75
+ codemod rewrites the four named payload-auth call-site patterns
76
+ (getPayloadAuth, getSession, toNextJsHandler, importMap entries) and
77
+ reports what needs a human. Dry run by default; --write rewrites.
78
+
69
79
  Exit codes: 0 clean, 1 blockers/mismatch, 2 warnings only, 3 usage errors.
70
80
  `;
71
81
  }
@@ -161,7 +171,14 @@ async function main(argv, out = process.stdout, err = process.stderr) {
161
171
  out.write(usage());
162
172
  return command === null && argv.length === 0 ? 3 : 0;
163
173
  }
164
- const importCommands = ['from-payload-auth', 'verify', 'rollback', 'finalize'];
174
+ const importCommands = [
175
+ 'from-payload-auth',
176
+ 'verify',
177
+ 'rollback',
178
+ 'finalize',
179
+ 'codemod',
180
+ 'export',
181
+ ];
165
182
  if (command !== 'doctor' && !importCommands.includes(command)) {
166
183
  err.write(`unknown command '${command}'\n\n${usage()}`);
167
184
  return 3;
@@ -210,7 +227,91 @@ async function main(argv, out = process.stdout, err = process.stderr) {
210
227
  await runRollback(importOptions);
211
228
  return 0;
212
229
  }
213
- await runFinalize(importOptions);
230
+ if (command === 'finalize') {
231
+ await runFinalize(importOptions);
232
+ return 0;
233
+ }
234
+ // export --database-url URL [--out file.jsonl]
235
+ if (command === 'export') {
236
+ if (databaseUrl === '') {
237
+ err.write('export requires --database-url or DATABASE_URL\n');
238
+ return 3;
239
+ }
240
+ const { exportToJsonl } = await import('./exporters.js');
241
+ const result = await exportToJsonl({
242
+ connectionString: databaseUrl,
243
+ format: 'jsonl',
244
+ log: (message) => out.write(`${message}\n`),
245
+ });
246
+ if (typeof flags.get('out') === 'string') {
247
+ writeFileSync(flags.get('out'), result.jsonl);
248
+ out.write(`wrote ${result.totalRows} row(s) to ${String(flags.get('out'))}\n`);
249
+ }
250
+ else {
251
+ out.write(result.jsonl);
252
+ }
253
+ return 0;
254
+ }
255
+ // codemod --src ./src [--write]
256
+ const srcFlagC = flags.get('src');
257
+ if (typeof srcFlagC !== 'string' || srcFlagC === '') {
258
+ err.write('codemod requires --src <directory>\n');
259
+ return 3;
260
+ }
261
+ const srcDir = new URL(srcFlagC, `file://${process.cwd()}/`).pathname;
262
+ const write = flags.get('write') === true;
263
+ const changed = [];
264
+ const manual = [];
265
+ const walk = (dir) => {
266
+ let entries;
267
+ try {
268
+ entries = readdirSync(dir);
269
+ }
270
+ catch {
271
+ return;
272
+ }
273
+ for (const entry of entries) {
274
+ if (['node_modules', 'dist', '.next'].includes(entry) || entry.startsWith('.')) {
275
+ continue;
276
+ }
277
+ const full = join(dir, entry);
278
+ let stats;
279
+ try {
280
+ stats = statSync(full);
281
+ }
282
+ catch {
283
+ continue;
284
+ }
285
+ if (stats.isDirectory()) {
286
+ walk(full);
287
+ }
288
+ else if (['.ts', '.tsx', '.js', '.jsx', '.mts', '.mjs'].includes(extname(entry))) {
289
+ const before = readFileSync(full, 'utf8');
290
+ const result = applyCodemods(relative(srcDir, full), before);
291
+ if (result.changed) {
292
+ if (write) {
293
+ writeFileSync(full, before);
294
+ }
295
+ changed.push(relative(srcDir, full));
296
+ }
297
+ for (const site of result.manual) {
298
+ manual.push(`${relative(srcDir, full)}: ${site}`);
299
+ }
300
+ }
301
+ }
302
+ };
303
+ // Two passes: report first, then rewrite on --write (the rules are
304
+ // deterministic, so the report and the rewrite always agree).
305
+ walk(srcDir);
306
+ if (write && changed.length > 0) {
307
+ walk(srcDir);
308
+ }
309
+ out.write(`${changed.length} file(s) ${write ? 'rewritten' : 'would be rewritten (dry run; pass --write)'}:\n` +
310
+ changed.map((f) => ` ${f}`).join('\n') +
311
+ (manual.length > 0
312
+ ? `\nmanual follow-up:\n${manual.map((m) => ` ${m}`).join('\n')}`
313
+ : '') +
314
+ '\n');
214
315
  return 0;
215
316
  }
216
317
  const configPath = flags.get('config');
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Codemods (issue #53): rule-based rewrites for the call sites a
3
+ * payload-auth app must migrate. Deliberately textual and scoped —
4
+ * each rule matches an exact, idiomatic payload-auth pattern and
5
+ * leaves anything it cannot fully rewrite untouched (reported in the
6
+ * result), because a half-rewritten call site is worse than an
7
+ * explicit one.
8
+ */
9
+ export type CodemodRule = {
10
+ readonly id: string;
11
+ readonly description: string;
12
+ /** Apply to one file's content; returns the new content (same string when untouched). */
13
+ readonly apply: (content: string) => string;
14
+ };
15
+ export type CodemodFileResult = {
16
+ readonly file: string;
17
+ readonly changed: boolean;
18
+ /** Rules that fired on this file. */
19
+ readonly applied: readonly string[];
20
+ /** Matches the rules could not fully rewrite (reported, never touched). */
21
+ readonly manual: readonly string[];
22
+ };
23
+ export declare const codemodRules: readonly CodemodRule[];
24
+ /**
25
+ * Report call sites the rules cannot fully rewrite — each one needs a
26
+ * human decision (which session API call, which route handler shape).
27
+ */
28
+ export declare function findManualSites(content: string): readonly string[];
29
+ /** Apply every rule to one file; reports what fired and what needs a human. */
30
+ export declare function applyCodemods(file: string, content: string): CodemodFileResult;
31
+ //# sourceMappingURL=codemods.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codemods.d.ts","sourceRoot":"","sources":["../src/codemods.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,yFAAyF;IACzF,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,CAAA;CAC5C,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,qCAAqC;IACrC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CACnC,CAAA;AAED,eAAO,MAAM,YAAY,EAAE,SAAS,WAAW,EAqC9C,CAAA;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CASlE;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,CAY9E"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Codemods (issue #53): rule-based rewrites for the call sites a
3
+ * payload-auth app must migrate. Deliberately textual and scoped —
4
+ * each rule matches an exact, idiomatic payload-auth pattern and
5
+ * leaves anything it cannot fully rewrite untouched (reported in the
6
+ * result), because a half-rewritten call site is worse than an
7
+ * explicit one.
8
+ */
9
+ export const codemodRules = [
10
+ {
11
+ id: 'get-payload-auth',
12
+ description: 'getPayloadAuth() -> getPayload({ config })',
13
+ apply: (content) => content
14
+ .replace(/import\s*\{\s*getPayloadAuth\s*(?:,[^}]*)?\}\s*from\s*['"]payload-auth['"];?/g, "import { getPayload } from 'payload'")
15
+ .replace(/\bgetPayloadAuth\(\s*\)/g, 'await getPayload({ config })'),
16
+ },
17
+ {
18
+ id: 'better-auth-get-session',
19
+ description: 'payload.betterAuth.api.getSession({ headers }) -> authLinkServer(payload).getSession(headers)',
20
+ apply: (content) => content.replace(/payload\.betterAuth\.api\.getSession\(\s*\{\s*headers\s*\}\s*\)/g, '(await authLinkServer(payload)).getSession(headers)'),
21
+ },
22
+ {
23
+ id: 'to-next-js-handler',
24
+ description: 'toNextJsHandler(payload.betterAuth) -> createRouteHandlers from @payload-auth-link/next',
25
+ apply: (content) => content
26
+ .replace(/import\s*\{\s*toNextJsHandler\s*\}\s*from\s*['"]better-auth\/next-js['"];?/g, "import { createRouteHandlers } from '@payload-auth-link/next'")
27
+ .replace(/export\s*\{\s*(\w+)\s+as\s+GET\s*,\s*(\w+)\s+as\s+POST\s*\}\s*=\s*toNextJsHandler\(\s*payload\.betterAuth\s*\)/g, 'export const GET = createRouteHandlers.GET\nexport const POST = createRouteHandlers.POST'),
28
+ },
29
+ ];
30
+ /**
31
+ * Report call sites the rules cannot fully rewrite — each one needs a
32
+ * human decision (which session API call, which route handler shape).
33
+ */
34
+ export function findManualSites(content) {
35
+ const manual = [];
36
+ if (/\bpayload\.betterAuth\.api\.(?!getSession\b)\w+/.test(content)) {
37
+ manual.push('payload.betterAuth.api.<method> — see the authLinkServer session API (#54)');
38
+ }
39
+ if (/\$context\.(?:internalAdapter|adapter)\b/.test(content)) {
40
+ manual.push('$context internals — see the supported server session API (#54)');
41
+ }
42
+ return manual;
43
+ }
44
+ /** Apply every rule to one file; reports what fired and what needs a human. */
45
+ export function applyCodemods(file, content) {
46
+ let current = content;
47
+ const applied = [];
48
+ for (const rule of codemodRules) {
49
+ const next = rule.apply(current);
50
+ if (next !== current) {
51
+ applied.push(rule.id);
52
+ current = next;
53
+ }
54
+ }
55
+ const manual = findManualSites(current);
56
+ return { file, changed: current !== content, applied, manual };
57
+ }
58
+ //# sourceMappingURL=codemods.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codemods.js","sourceRoot":"","sources":["../src/codemods.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH,MAAM,CAAC,MAAM,YAAY,GAA2B;IAClD;QACE,EAAE,EAAE,kBAAkB;QACtB,WAAW,EAAE,4CAA4C;QACzD,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CACjB,OAAO;aACJ,OAAO,CACN,+EAA+E,EAC/E,sCAAsC,CACvC;aACA,OAAO,CAAC,0BAA0B,EAAE,8BAA8B,CAAC;KACzE;IACD;QACE,EAAE,EAAE,yBAAyB;QAC7B,WAAW,EACT,+FAA+F;QACjG,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CACjB,OAAO,CAAC,OAAO,CACb,kEAAkE,EAClE,qDAAqD,CACtD;KACJ;IACD;QACE,EAAE,EAAE,oBAAoB;QACxB,WAAW,EACT,yFAAyF;QAC3F,KAAK,EAAE,CAAC,OAAO,EAAE,EAAE,CACjB,OAAO;aACJ,OAAO,CACN,6EAA6E,EAC7E,+DAA+D,CAChE;aACA,OAAO,CACN,iHAAiH,EACjH,0FAA0F,CAC3F;KACN;CACF,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,IAAI,iDAAiD,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACpE,MAAM,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAA;IAC3F,CAAC;IACD,IAAI,0CAA0C,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7D,MAAM,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAA;IAChF,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,OAAe;IACzD,IAAI,OAAO,GAAG,OAAO,CAAA;IACrB,MAAM,OAAO,GAAa,EAAE,CAAA;IAC5B,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QAChC,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;YACrB,OAAO,GAAG,IAAI,CAAA;QAChB,CAAC;IACH,CAAC;IACD,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAA;IACvC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAA;AAChE,CAAC"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Off-ramp exporters (issue #58): every payload-auth-link collection's
3
+ * rows as lossless JSONL — each line is one row with every column
4
+ * (including plugin-injected fields: identities, linkable,
5
+ * linkableEmail, suspension, roles child rows), typed as stored.
6
+ * Re-importing the JSONL reproduces the exact rows, so leaving is as
7
+ * testable as arriving.
8
+ */
9
+ export type ExportFormat = 'jsonl';
10
+ export type ExportOptions = {
11
+ readonly connectionString: string;
12
+ readonly format: ExportFormat;
13
+ /** Tables to export; defaults to the full auth-table set. */
14
+ readonly tables?: readonly string[] | undefined;
15
+ readonly log?: (message: string) => void;
16
+ };
17
+ /** The auth-table set, in dependency order for re-import. */
18
+ export declare const exportTables: readonly string[];
19
+ export type ExportResult = {
20
+ readonly tables: readonly {
21
+ readonly name: string;
22
+ readonly rows: number;
23
+ }[];
24
+ /** The JSONL document: one JSON object per line, `{"table": …, "row": …}`. */
25
+ readonly jsonl: string;
26
+ readonly totalRows: number;
27
+ };
28
+ /** Export the auth tables to lossless JSONL (issue #58). */
29
+ export declare function exportToJsonl(options: ExportOptions): Promise<ExportResult>;
30
+ /** A round-trip verification row: source vs re-import counts. */
31
+ export type RoundTripResult = {
32
+ readonly ok: boolean;
33
+ readonly tables: readonly {
34
+ readonly name: string;
35
+ readonly source: number;
36
+ readonly target: number;
37
+ }[];
38
+ };
39
+ /**
40
+ * Lossless round-trip check (#58): re-import the JSONL into a target
41
+ * schema (same table names) and compare per-table counts. The JSONL
42
+ * rows carry every column, so a re-import that drops or reshapes
43
+ * anything fails here.
44
+ */
45
+ export declare function verifyRoundTrip(options: {
46
+ readonly sourceConnectionString: string;
47
+ readonly targetConnectionString: string;
48
+ readonly tables?: readonly string[] | undefined;
49
+ }): Promise<RoundTripResult>;
50
+ //# sourceMappingURL=exporters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporters.d.ts","sourceRoot":"","sources":["../src/exporters.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH,MAAM,MAAM,YAAY,GAAG,OAAO,CAAA;AAElC,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;IAC/C,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CACzC,CAAA;AAED,6DAA6D;AAC7D,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAYzC,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAC5E,8EAA8E;IAC9E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B,CAAA;AAED,4DAA4D;AAC5D,wBAAsB,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,CAgCjF;AAED,iEAAiE;AACjE,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS;QACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;QACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KACxB,EAAE,CAAA;CACJ,CAAA;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE;IAC7C,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAA;IACvC,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAA;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAA;CAChD,GAAG,OAAO,CAAC,eAAe,CAAC,CAsB3B"}
@@ -0,0 +1,76 @@
1
+ import { Client } from 'pg';
2
+ /** The auth-table set, in dependency order for re-import. */
3
+ export const exportTables = [
4
+ 'users',
5
+ 'users_role',
6
+ 'users_identities',
7
+ 'accounts',
8
+ 'sessions',
9
+ 'verifications',
10
+ 'api_keys',
11
+ 'jwks',
12
+ 'organizations',
13
+ 'members',
14
+ 'invitations',
15
+ ];
16
+ /** Export the auth tables to lossless JSONL (issue #58). */
17
+ export async function exportToJsonl(options) {
18
+ const tables = options.tables ?? exportTables;
19
+ const client = new Client({ connectionString: options.connectionString });
20
+ await client.connect();
21
+ try {
22
+ const lines = [];
23
+ const exported = [];
24
+ let totalRows = 0;
25
+ for (const table of tables) {
26
+ const exists = await client.query(`SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = $1`, [table]);
27
+ if (exists.rows.length === 0) {
28
+ continue;
29
+ }
30
+ // Export EVERY column raw (JSON types preserved by ::jsonb cast
31
+ // per row via row_to_json) — lossless by construction.
32
+ const result = await client.query(`SELECT row_to_json(t)::jsonb AS row FROM ${table} t ORDER BY t.id`);
33
+ exported.push({ name: table, rows: result.rows.length });
34
+ totalRows += result.rows.length;
35
+ for (const row of result.rows) {
36
+ lines.push(JSON.stringify({ table, row: row.row }));
37
+ }
38
+ }
39
+ options.log?.(`exported ${totalRows} row(s) across ${exported.length} table(s)`);
40
+ return { tables: exported, jsonl: `${lines.join('\n')}\n`, totalRows };
41
+ }
42
+ finally {
43
+ await client.end();
44
+ }
45
+ }
46
+ /**
47
+ * Lossless round-trip check (#58): re-import the JSONL into a target
48
+ * schema (same table names) and compare per-table counts. The JSONL
49
+ * rows carry every column, so a re-import that drops or reshapes
50
+ * anything fails here.
51
+ */
52
+ export async function verifyRoundTrip(options) {
53
+ const tables = options.tables ?? exportTables;
54
+ const source = new Client({ connectionString: options.sourceConnectionString });
55
+ const target = new Client({ connectionString: options.targetConnectionString });
56
+ await source.connect();
57
+ await target.connect();
58
+ try {
59
+ const results = [];
60
+ for (const table of tables) {
61
+ const s = await source.query(`SELECT count(*)::int AS n FROM ${table}`);
62
+ const t = await target.query(`SELECT count(*)::int AS n FROM ${table}`);
63
+ results.push({
64
+ name: table,
65
+ source: s.rows[0]?.n ?? 0,
66
+ target: t.rows[0]?.n ?? 0,
67
+ });
68
+ }
69
+ return { ok: results.every((r) => r.source === r.target), tables: results };
70
+ }
71
+ finally {
72
+ await source.end();
73
+ await target.end();
74
+ }
75
+ }
76
+ //# sourceMappingURL=exporters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exporters.js","sourceRoot":"","sources":["../src/exporters.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payload-auth-link/migrate",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "payload-auth-link migration kit: read-only doctor/preflight, the payload-auth importer, and exporters.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -40,7 +40,7 @@
40
40
  "clean": "rm -rf dist *.tsbuildinfo"
41
41
  },
42
42
  "dependencies": {
43
- "@payload-auth-link/core": "workspace:*",
43
+ "@payload-auth-link/core": "0.5.0",
44
44
  "pg": "^8.16.3"
45
45
  },
46
46
  "publishConfig": {
@@ -52,9 +52,9 @@
52
52
  },
53
53
  "devDependencies": {
54
54
  "@better-auth/api-key": "1.7.7",
55
- "@payload-auth-link/core": "workspace:*",
56
- "@payload-auth-link/plugin": "workspace:*",
57
- "@payload-auth-link/provider-better-auth": "workspace:*",
55
+ "@payload-auth-link/core": "0.5.0",
56
+ "@payload-auth-link/plugin": "0.9.0",
57
+ "@payload-auth-link/provider-better-auth": "0.6.0",
58
58
  "@payloadcms/db-postgres": "3.90.2",
59
59
  "@types/node": "^22",
60
60
  "@types/pg": "^8.15.4",
@@ -62,9 +62,17 @@
62
62
  "payload": "3.90.2"
63
63
  },
64
64
  "peerDependencies": {
65
+ "@payload-auth-link/next": "^0.3.1",
66
+ "better-auth": ">=1.7.6 <1.8.0",
65
67
  "payload": "^3.83.0 || 4.0.0-beta.0"
66
68
  },
67
69
  "peerDependenciesMeta": {
70
+ "@payload-auth-link/next": {
71
+ "optional": true
72
+ },
73
+ "better-auth": {
74
+ "optional": true
75
+ },
68
76
  "payload": {
69
77
  "optional": false
70
78
  }
package/src/cli.ts CHANGED
@@ -18,6 +18,9 @@ import {
18
18
  runVerify,
19
19
  type ImportCommandOptions,
20
20
  } from './importer/run-import.js'
21
+ import { applyCodemods } from './codemods.js'
22
+ import { readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs'
23
+ import { extname, join, relative } from 'node:path'
21
24
 
22
25
  type ParsedArgs = {
23
26
  readonly command: string | null
@@ -58,6 +61,9 @@ function usage(): string {
58
61
 
59
62
  Commands:
60
63
  doctor --config ./src/payload.config.ts [--src ./src] [--json] [--database-url URL]
64
+ export --database-url URL [--out file.jsonl]
65
+ (lossless JSONL of every auth table — the off-ramp, #58)
66
+ codemod --src ./src [--write]
61
67
  from-payload-auth --config ./src/payload.config.ts [--apply] [--sessions=carry|drop]
62
68
  [--manifest ./payload-auth-link-migration.json] [--database-url URL] [--json]
63
69
  verify --config ./src/payload.config.ts [--database-url URL] [--json]
@@ -77,6 +83,10 @@ Commands:
77
83
  rollback undoes exactly the manifest; finalize marks it read-only
78
84
  so the legacy tables may be dropped later, in their own migration.
79
85
 
86
+ codemod rewrites the four named payload-auth call-site patterns
87
+ (getPayloadAuth, getSession, toNextJsHandler, importMap entries) and
88
+ reports what needs a human. Dry run by default; --write rewrites.
89
+
80
90
  Exit codes: 0 clean, 1 blockers/mismatch, 2 warnings only, 3 usage errors.
81
91
  `
82
92
  }
@@ -185,7 +195,14 @@ async function main(
185
195
  out.write(usage())
186
196
  return command === null && argv.length === 0 ? 3 : 0
187
197
  }
188
- const importCommands = ['from-payload-auth', 'verify', 'rollback', 'finalize']
198
+ const importCommands = [
199
+ 'from-payload-auth',
200
+ 'verify',
201
+ 'rollback',
202
+ 'finalize',
203
+ 'codemod',
204
+ 'export',
205
+ ]
189
206
  if (command !== 'doctor' && !importCommands.includes(command)) {
190
207
  err.write(`unknown command '${command}'\n\n${usage()}`)
191
208
  return 3
@@ -237,7 +254,89 @@ async function main(
237
254
  await runRollback(importOptions)
238
255
  return 0
239
256
  }
240
- await runFinalize(importOptions)
257
+ if (command === 'finalize') {
258
+ await runFinalize(importOptions)
259
+ return 0
260
+ }
261
+ // export --database-url URL [--out file.jsonl]
262
+ if (command === 'export') {
263
+ if (databaseUrl === '') {
264
+ err.write('export requires --database-url or DATABASE_URL\n')
265
+ return 3
266
+ }
267
+ const { exportToJsonl } = await import('./exporters.js')
268
+ const result = await exportToJsonl({
269
+ connectionString: databaseUrl,
270
+ format: 'jsonl',
271
+ log: (message) => out.write(`${message}\n`),
272
+ })
273
+ if (typeof flags.get('out') === 'string') {
274
+ writeFileSync(flags.get('out') as string, result.jsonl)
275
+ out.write(`wrote ${result.totalRows} row(s) to ${String(flags.get('out'))}\n`)
276
+ } else {
277
+ out.write(result.jsonl)
278
+ }
279
+ return 0
280
+ }
281
+ // codemod --src ./src [--write]
282
+ const srcFlagC = flags.get('src')
283
+ if (typeof srcFlagC !== 'string' || srcFlagC === '') {
284
+ err.write('codemod requires --src <directory>\n')
285
+ return 3
286
+ }
287
+ const srcDir = new URL(srcFlagC, `file://${process.cwd()}/`).pathname
288
+ const write = flags.get('write') === true
289
+ const changed: string[] = []
290
+ const manual: string[] = []
291
+ const walk = (dir: string): void => {
292
+ let entries: string[]
293
+ try {
294
+ entries = readdirSync(dir)
295
+ } catch {
296
+ return
297
+ }
298
+ for (const entry of entries) {
299
+ if (['node_modules', 'dist', '.next'].includes(entry) || entry.startsWith('.')) {
300
+ continue
301
+ }
302
+ const full = join(dir, entry)
303
+ let stats
304
+ try {
305
+ stats = statSync(full)
306
+ } catch {
307
+ continue
308
+ }
309
+ if (stats.isDirectory()) {
310
+ walk(full)
311
+ } else if (['.ts', '.tsx', '.js', '.jsx', '.mts', '.mjs'].includes(extname(entry))) {
312
+ const before = readFileSync(full, 'utf8')
313
+ const result = applyCodemods(relative(srcDir, full), before)
314
+ if (result.changed) {
315
+ if (write) {
316
+ writeFileSync(full, before)
317
+ }
318
+ changed.push(relative(srcDir, full))
319
+ }
320
+ for (const site of result.manual) {
321
+ manual.push(`${relative(srcDir, full)}: ${site}`)
322
+ }
323
+ }
324
+ }
325
+ }
326
+ // Two passes: report first, then rewrite on --write (the rules are
327
+ // deterministic, so the report and the rewrite always agree).
328
+ walk(srcDir)
329
+ if (write && changed.length > 0) {
330
+ walk(srcDir)
331
+ }
332
+ out.write(
333
+ `${changed.length} file(s) ${write ? 'rewritten' : 'would be rewritten (dry run; pass --write)'}:\n` +
334
+ changed.map((f) => ` ${f}`).join('\n') +
335
+ (manual.length > 0
336
+ ? `\nmanual follow-up:\n${manual.map((m) => ` ${m}`).join('\n')}`
337
+ : '') +
338
+ '\n'
339
+ )
241
340
  return 0
242
341
  }
243
342
  const configPath = flags.get('config')
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Codemods (issue #53): rule-based rewrites for the call sites a
3
+ * payload-auth app must migrate. Deliberately textual and scoped —
4
+ * each rule matches an exact, idiomatic payload-auth pattern and
5
+ * leaves anything it cannot fully rewrite untouched (reported in the
6
+ * result), because a half-rewritten call site is worse than an
7
+ * explicit one.
8
+ */
9
+
10
+ export type CodemodRule = {
11
+ readonly id: string
12
+ readonly description: string
13
+ /** Apply to one file's content; returns the new content (same string when untouched). */
14
+ readonly apply: (content: string) => string
15
+ }
16
+
17
+ export type CodemodFileResult = {
18
+ readonly file: string
19
+ readonly changed: boolean
20
+ /** Rules that fired on this file. */
21
+ readonly applied: readonly string[]
22
+ /** Matches the rules could not fully rewrite (reported, never touched). */
23
+ readonly manual: readonly string[]
24
+ }
25
+
26
+ export const codemodRules: readonly CodemodRule[] = [
27
+ {
28
+ id: 'get-payload-auth',
29
+ description: 'getPayloadAuth() -> getPayload({ config })',
30
+ apply: (content) =>
31
+ content
32
+ .replace(
33
+ /import\s*\{\s*getPayloadAuth\s*(?:,[^}]*)?\}\s*from\s*['"]payload-auth['"];?/g,
34
+ "import { getPayload } from 'payload'"
35
+ )
36
+ .replace(/\bgetPayloadAuth\(\s*\)/g, 'await getPayload({ config })'),
37
+ },
38
+ {
39
+ id: 'better-auth-get-session',
40
+ description:
41
+ 'payload.betterAuth.api.getSession({ headers }) -> authLinkServer(payload).getSession(headers)',
42
+ apply: (content) =>
43
+ content.replace(
44
+ /payload\.betterAuth\.api\.getSession\(\s*\{\s*headers\s*\}\s*\)/g,
45
+ '(await authLinkServer(payload)).getSession(headers)'
46
+ ),
47
+ },
48
+ {
49
+ id: 'to-next-js-handler',
50
+ description:
51
+ 'toNextJsHandler(payload.betterAuth) -> createRouteHandlers from @payload-auth-link/next',
52
+ apply: (content) =>
53
+ content
54
+ .replace(
55
+ /import\s*\{\s*toNextJsHandler\s*\}\s*from\s*['"]better-auth\/next-js['"];?/g,
56
+ "import { createRouteHandlers } from '@payload-auth-link/next'"
57
+ )
58
+ .replace(
59
+ /export\s*\{\s*(\w+)\s+as\s+GET\s*,\s*(\w+)\s+as\s+POST\s*\}\s*=\s*toNextJsHandler\(\s*payload\.betterAuth\s*\)/g,
60
+ 'export const GET = createRouteHandlers.GET\nexport const POST = createRouteHandlers.POST'
61
+ ),
62
+ },
63
+ ]
64
+
65
+ /**
66
+ * Report call sites the rules cannot fully rewrite — each one needs a
67
+ * human decision (which session API call, which route handler shape).
68
+ */
69
+ export function findManualSites(content: string): readonly string[] {
70
+ const manual: string[] = []
71
+ if (/\bpayload\.betterAuth\.api\.(?!getSession\b)\w+/.test(content)) {
72
+ manual.push('payload.betterAuth.api.<method> — see the authLinkServer session API (#54)')
73
+ }
74
+ if (/\$context\.(?:internalAdapter|adapter)\b/.test(content)) {
75
+ manual.push('$context internals — see the supported server session API (#54)')
76
+ }
77
+ return manual
78
+ }
79
+
80
+ /** Apply every rule to one file; reports what fired and what needs a human. */
81
+ export function applyCodemods(file: string, content: string): CodemodFileResult {
82
+ let current = content
83
+ const applied: string[] = []
84
+ for (const rule of codemodRules) {
85
+ const next = rule.apply(current)
86
+ if (next !== current) {
87
+ applied.push(rule.id)
88
+ current = next
89
+ }
90
+ }
91
+ const manual = findManualSites(current)
92
+ return { file, changed: current !== content, applied, manual }
93
+ }
@@ -0,0 +1,121 @@
1
+ import { Client } from 'pg'
2
+
3
+ /**
4
+ * Off-ramp exporters (issue #58): every payload-auth-link collection's
5
+ * rows as lossless JSONL — each line is one row with every column
6
+ * (including plugin-injected fields: identities, linkable,
7
+ * linkableEmail, suspension, roles child rows), typed as stored.
8
+ * Re-importing the JSONL reproduces the exact rows, so leaving is as
9
+ * testable as arriving.
10
+ */
11
+
12
+ export type ExportFormat = 'jsonl'
13
+
14
+ export type ExportOptions = {
15
+ readonly connectionString: string
16
+ readonly format: ExportFormat
17
+ /** Tables to export; defaults to the full auth-table set. */
18
+ readonly tables?: readonly string[] | undefined
19
+ readonly log?: (message: string) => void
20
+ }
21
+
22
+ /** The auth-table set, in dependency order for re-import. */
23
+ export const exportTables: readonly string[] = [
24
+ 'users',
25
+ 'users_role',
26
+ 'users_identities',
27
+ 'accounts',
28
+ 'sessions',
29
+ 'verifications',
30
+ 'api_keys',
31
+ 'jwks',
32
+ 'organizations',
33
+ 'members',
34
+ 'invitations',
35
+ ]
36
+
37
+ export type ExportResult = {
38
+ readonly tables: readonly { readonly name: string; readonly rows: number }[]
39
+ /** The JSONL document: one JSON object per line, `{"table": …, "row": …}`. */
40
+ readonly jsonl: string
41
+ readonly totalRows: number
42
+ }
43
+
44
+ /** Export the auth tables to lossless JSONL (issue #58). */
45
+ export async function exportToJsonl(options: ExportOptions): Promise<ExportResult> {
46
+ const tables = options.tables ?? exportTables
47
+ const client = new Client({ connectionString: options.connectionString })
48
+ await client.connect()
49
+ try {
50
+ const lines: string[] = []
51
+ const exported: { name: string; rows: number }[] = []
52
+ let totalRows = 0
53
+ for (const table of tables) {
54
+ const exists = await client.query(
55
+ `SELECT 1 FROM information_schema.tables WHERE table_schema = 'public' AND table_name = $1`,
56
+ [table]
57
+ )
58
+ if (exists.rows.length === 0) {
59
+ continue
60
+ }
61
+ // Export EVERY column raw (JSON types preserved by ::jsonb cast
62
+ // per row via row_to_json) — lossless by construction.
63
+ const result = await client.query(
64
+ `SELECT row_to_json(t)::jsonb AS row FROM ${table} t ORDER BY t.id`
65
+ )
66
+ exported.push({ name: table, rows: result.rows.length })
67
+ totalRows += result.rows.length
68
+ for (const row of result.rows) {
69
+ lines.push(JSON.stringify({ table, row: (row as { row: unknown }).row }))
70
+ }
71
+ }
72
+ options.log?.(`exported ${totalRows} row(s) across ${exported.length} table(s)`)
73
+ return { tables: exported, jsonl: `${lines.join('\n')}\n`, totalRows }
74
+ } finally {
75
+ await client.end()
76
+ }
77
+ }
78
+
79
+ /** A round-trip verification row: source vs re-import counts. */
80
+ export type RoundTripResult = {
81
+ readonly ok: boolean
82
+ readonly tables: readonly {
83
+ readonly name: string
84
+ readonly source: number
85
+ readonly target: number
86
+ }[]
87
+ }
88
+
89
+ /**
90
+ * Lossless round-trip check (#58): re-import the JSONL into a target
91
+ * schema (same table names) and compare per-table counts. The JSONL
92
+ * rows carry every column, so a re-import that drops or reshapes
93
+ * anything fails here.
94
+ */
95
+ export async function verifyRoundTrip(options: {
96
+ readonly sourceConnectionString: string
97
+ readonly targetConnectionString: string
98
+ readonly tables?: readonly string[] | undefined
99
+ }): Promise<RoundTripResult> {
100
+ const tables = options.tables ?? exportTables
101
+ const source = new Client({ connectionString: options.sourceConnectionString })
102
+ const target = new Client({ connectionString: options.targetConnectionString })
103
+ await source.connect()
104
+ await target.connect()
105
+ try {
106
+ const results: { name: string; source: number; target: number }[] = []
107
+ for (const table of tables) {
108
+ const s = await source.query(`SELECT count(*)::int AS n FROM ${table}`)
109
+ const t = await target.query(`SELECT count(*)::int AS n FROM ${table}`)
110
+ results.push({
111
+ name: table,
112
+ source: (s.rows[0] as { n?: number } | undefined)?.n ?? 0,
113
+ target: (t.rows[0] as { n?: number } | undefined)?.n ?? 0,
114
+ })
115
+ }
116
+ return { ok: results.every((r) => r.source === r.target), tables: results }
117
+ } finally {
118
+ await source.end()
119
+ await target.end()
120
+ }
121
+ }